summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--cmake/Modules/FindThrift.cmake79
-rw-r--r--cmake/Modules/GrSwig.cmake41
-rw-r--r--cmake/Modules/GrTest.cmake3
-rw-r--r--config.h.in6
-rw-r--r--docs/doxygen/other/build_guide.dox13
-rw-r--r--docs/doxygen/other/ctrlport.dox425
-rw-r--r--docs/doxygen/other/perf_counters.dox10
-rw-r--r--gnuradio-runtime/include/gnuradio/CMakeLists.txt10
-rw-r--r--gnuradio-runtime/include/gnuradio/prefs.h32
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcbufferedget.h64
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcmanager.h2
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h75
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h22
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h51
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcserver_selector.h10
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcserver_thrift.h233
-rw-r--r--gnuradio-runtime/include/gnuradio/thrift_application_base.h252
-rw-r--r--gnuradio-runtime/include/gnuradio/thrift_server_template.h159
-rw-r--r--gnuradio-runtime/lib/CMakeLists.txt36
-rw-r--r--gnuradio-runtime/lib/block.cc12
-rw-r--r--gnuradio-runtime/lib/controlport/CMakeLists.txt70
-rw-r--r--gnuradio-runtime/lib/controlport/rpcmanager.cc14
-rw-r--r--gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc3
-rw-r--r--gnuradio-runtime/lib/controlport/rpcserver_selector.cc15
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/README41
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/gnuradio.thrift108
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/rpcpmtconverters_thrift.cc303
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/rpcserver_booter_thrift.cc133
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/rpcserver_thrift.cc202
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/thrift-codebase-shutdown-patch.diff98
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/thrift.conf.example4
-rw-r--r--gnuradio-runtime/lib/controlport/thrift/thrift_application_base.cc23
-rw-r--r--gnuradio-runtime/lib/prefs.cc28
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt43
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py132
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py6
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py115
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py208
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor771
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx875
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/monitor.py6
-rwxr-xr-xgnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py32
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/tag_utils.py33
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/top_block.py11
-rw-r--r--gnuradio-runtime/swig/gr_types.i20
-rw-r--r--gnuradio-runtime/swig/prefs.i4
-rw-r--r--gr-analog/examples/CMakeLists.txt7
-rw-r--r--gr-analog/examples/noise_power.grc1675
-rw-r--r--gr-analog/grc/analog_pwr_squelch_xx.xml2
-rw-r--r--gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t23
-rw-r--r--gr-analog/include/gnuradio/analog/noise_source_X.h.t23
-rw-r--r--gr-analog/include/gnuradio/analog/pwr_squelch_cc.h10
-rw-r--r--gr-analog/include/gnuradio/analog/pwr_squelch_ff.h10
-rw-r--r--gr-analog/lib/fastnoise_source_X_impl.cc.t9
-rw-r--r--gr-analog/lib/noise_source_X_impl.cc.t9
-rw-r--r--gr-analog/lib/squelch_base_cc_impl.cc101
-rw-r--r--gr-analog/lib/squelch_base_cc_impl.h2
-rw-r--r--gr-analog/lib/squelch_base_ff_impl.cc105
-rw-r--r--gr-analog/lib/squelch_base_ff_impl.h3
-rw-r--r--gr-audio/grc/audio_sink.xml2
-rw-r--r--gr-audio/grc/audio_source.xml2
-rw-r--r--gr-blocks/examples/CMakeLists.txt1
-rw-r--r--gr-blocks/examples/peak_detector2.grc1045
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml2
-rw-r--r--gr-blocks/grc/blocks_ctrlport_performance.xml48
-rw-r--r--gr-blocks/grc/blocks_ctrlport_viewer.xml48
-rw-r--r--gr-blocks/grc/blocks_peak_detector2_fb.xml5
-rw-r--r--gr-blocks/grc/blocks_throttle.xml2
-rw-r--r--gr-blocks/grc/blocks_udp_source.xml2
-rw-r--r--gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h24
-rw-r--r--gr-blocks/lib/CMakeLists.txt22
-rw-r--r--gr-blocks/lib/ctrlport_probe2_b_impl.cc51
-rw-r--r--gr-blocks/lib/ctrlport_probe2_b_impl.h8
-rw-r--r--gr-blocks/lib/ctrlport_probe2_c_impl.cc51
-rw-r--r--gr-blocks/lib/ctrlport_probe2_c_impl.h8
-rw-r--r--gr-blocks/lib/ctrlport_probe2_f_impl.cc51
-rw-r--r--gr-blocks/lib/ctrlport_probe2_f_impl.h8
-rw-r--r--gr-blocks/lib/ctrlport_probe2_i_impl.cc51
-rw-r--r--gr-blocks/lib/ctrlport_probe2_i_impl.h8
-rw-r--r--gr-blocks/lib/ctrlport_probe2_s_impl.cc50
-rw-r--r--gr-blocks/lib/ctrlport_probe2_s_impl.h8
-rw-r--r--gr-blocks/lib/peak_detector2_fb_impl.cc103
-rw-r--r--gr-blocks/lib/peak_detector2_fb_impl.h10
-rw-r--r--gr-blocks/python/blocks/CMakeLists.txt6
-rw-r--r--gr-blocks/python/blocks/qa_cpp_py_binding.py173
-rw-r--r--gr-blocks/python/blocks/qa_cpp_py_binding_set.py151
-rw-r--r--gr-blocks/python/blocks/qa_ctrlport_probes.py210
-rw-r--r--gr-blocks/python/blocks/qa_peak_detector2.py87
-rw-r--r--gr-digital/examples/CMakeLists.txt8
-rw-r--r--gr-digital/examples/burst_shaper.grc880
-rw-r--r--gr-digital/examples/demod/test_corr_est.grc3500
-rw-r--r--gr-digital/grc/digital_block_tree.xml4
-rw-r--r--gr-digital/grc/digital_burst_shaper.xml71
-rw-r--r--gr-digital/grc/digital_corr_est_cc.xml50
-rw-r--r--gr-digital/grc/digital_modulate_vector.xml34
-rw-r--r--gr-digital/grc/digital_msk_timing_recovery_cc.xml49
-rw-r--r--gr-digital/include/gnuradio/digital/CMakeLists.txt6
-rw-r--r--gr-digital/include/gnuradio/digital/burst_shaper_XX.h.t123
-rw-r--r--gr-digital/include/gnuradio/digital/corr_est_cc.h118
-rw-r--r--gr-digital/include/gnuradio/digital/modulate_vector.h70
-rw-r--r--gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h76
-rw-r--r--gr-digital/lib/CMakeLists.txt4
-rw-r--r--gr-digital/lib/burst_shaper_XX_impl.cc.t353
-rw-r--r--gr-digital/lib/burst_shaper_XX_impl.h.t90
-rw-r--r--gr-digital/lib/corr_est_cc_impl.cc331
-rw-r--r--gr-digital/lib/corr_est_cc_impl.h73
-rw-r--r--gr-digital/lib/modulate_vector.cc70
-rw-r--r--gr-digital/lib/msk_timing_recovery_cc_impl.cc210
-rw-r--r--gr-digital/lib/msk_timing_recovery_cc_impl.h72
-rw-r--r--gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc2
-rwxr-xr-xgr-digital/python/digital/qa_burst_shaper.py340
-rw-r--r--gr-digital/swig/digital_swig.i16
-rw-r--r--gr-dtv/examples/README.dvbt4
-rw-r--r--gr-dtv/examples/dvbt_tx_2k.grc2076
-rw-r--r--gr-dtv/examples/dvbt_tx_8k.grc2076
-rw-r--r--gr-dtv/grc/CMakeLists.txt8
-rw-r--r--gr-dtv/grc/dtv_block_tree.xml11
-rw-r--r--gr-dtv/grc/dtv_dvbt_bit_inner_interleaver.xml89
-rw-r--r--gr-dtv/grc/dtv_dvbt_convolutional_interleaver.xml43
-rw-r--r--gr-dtv/grc/dtv_dvbt_energy_dispersal.xml29
-rw-r--r--gr-dtv/grc/dtv_dvbt_inner_coder.xml112
-rw-r--r--gr-dtv/grc/dtv_dvbt_map.xml90
-rw-r--r--gr-dtv/grc/dtv_dvbt_reed_solomon_enc.xml70
-rw-r--r--gr-dtv/grc/dtv_dvbt_reference_signals.xml222
-rw-r--r--gr-dtv/grc/dtv_dvbt_symbol_inner_interleaver.xml56
-rw-r--r--gr-dtv/include/gnuradio/dtv/CMakeLists.txt9
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvb_config.h12
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_config.h11
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_framemapper_cc.h2
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_freqinterleaver_cc.h3
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_miso_cc.h3
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_p1insertion_cc.h3
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_paprtr_cc.h3
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt2_pilotgenerator_cc.h3
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_interleaver.h67
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_config.h45
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_convolutional_interleaver.h58
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_energy_dispersal.h58
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_inner_coder.h69
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_map.h65
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_enc.h61
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_reference_signals.h71
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbt_symbol_inner_interleaver.h66
-rw-r--r--gr-dtv/lib/CMakeLists.txt10
-rw-r--r--gr-dtv/lib/dvb/dvb_bbheader_bb_impl.cc15
-rw-r--r--gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h1
-rw-r--r--gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.cc191
-rw-r--r--gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.h65
-rw-r--r--gr-dtv/lib/dvbt/dvbt_configure.cc277
-rw-r--r--gr-dtv/lib/dvbt/dvbt_configure.h103
-rw-r--r--gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.cc89
-rw-r--r--gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.h52
-rw-r--r--gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.cc151
-rw-r--r--gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.h65
-rw-r--r--gr-dtv/lib/dvbt/dvbt_inner_coder_impl.cc257
-rw-r--r--gr-dtv/lib/dvbt/dvbt_inner_coder_impl.h78
-rw-r--r--gr-dtv/lib/dvbt/dvbt_map_impl.cc163
-rw-r--r--gr-dtv/lib/dvbt/dvbt_map_impl.h72
-rw-r--r--gr-dtv/lib/dvbt/dvbt_reed_solomon.cc475
-rw-r--r--gr-dtv/lib/dvbt/dvbt_reed_solomon.h70
-rw-r--r--gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.cc103
-rw-r--r--gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.h62
-rw-r--r--gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc1284
-rw-r--r--gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h258
-rw-r--r--gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc222
-rw-r--r--gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.h70
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.cc67
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.h5
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.cc4
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.h2
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.cc4
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.h2
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc8
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h2
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc6
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h2
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc4
-rw-r--r--gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h2
-rw-r--r--gr-dtv/swig/dtv_swig.i26
-rw-r--r--gr-fcd/grc/fcd_source_c.xml2
-rw-r--r--gr-fec/lib/gf2mat.cc4
-rw-r--r--gr-filter/examples/CMakeLists.txt1
-rw-r--r--gr-filter/examples/filter_taps.grc1299
-rw-r--r--gr-filter/grc/CMakeLists.txt5
-rw-r--r--gr-filter/grc/filter_block_tree.xml8
-rw-r--r--gr-filter/grc/variable_band_pass_filter_taps.xml97
-rw-r--r--gr-filter/grc/variable_band_reject_filter_taps.xml81
-rw-r--r--gr-filter/grc/variable_high_pass_filter_taps.xml75
-rw-r--r--gr-filter/grc/variable_low_pass_filter_taps.xml75
-rw-r--r--gr-filter/grc/variable_rrc_filter_taps.xml50
-rw-r--r--gr-qtgui/grc/qtgui_range.xml209
-rw-r--r--gr-qtgui/lib/vector_sink_f_impl.cc4
-rwxr-xr-xgr-qtgui/python/qtgui/range.py67
-rw-r--r--gr-uhd/doc/uhd.dox101
-rw-r--r--gr-uhd/examples/grc/uhd_msg_tune.grc1143
-rwxr-xr-xgr-uhd/examples/python/freq_hopping.py38
-rwxr-xr-xgr-uhd/examples/python/usrp_spectrum_sense.py12
-rw-r--r--gr-uhd/grc/gen_uhd_usrp_blocks.py2
-rw-r--r--gr-uhd/include/gnuradio/uhd/CMakeLists.txt1
-rw-r--r--gr-uhd/include/gnuradio/uhd/usrp_block.h564
-rw-r--r--gr-uhd/include/gnuradio/uhd/usrp_sink.h540
-rw-r--r--gr-uhd/include/gnuradio/uhd/usrp_source.h467
-rw-r--r--gr-uhd/lib/CMakeLists.txt1
-rw-r--r--gr-uhd/lib/usrp_block_impl.cc696
-rw-r--r--gr-uhd/lib/usrp_block_impl.h241
-rw-r--r--gr-uhd/lib/usrp_common.h211
-rw-r--r--gr-uhd/lib/usrp_sink_impl.cc321
-rw-r--r--gr-uhd/lib/usrp_sink_impl.h48
-rw-r--r--gr-uhd/lib/usrp_source_impl.cc262
-rw-r--r--gr-uhd/lib/usrp_source_impl.h47
-rw-r--r--gr-uhd/swig/uhd_swig.i2
-rw-r--r--grc/base/Block.py98
-rw-r--r--grc/base/Constants.py8
-rw-r--r--grc/base/FlowGraph.py68
-rw-r--r--grc/gui/ActionHandler.py42
-rw-r--r--grc/gui/Actions.py6
-rw-r--r--grc/gui/Bars.py3
-rw-r--r--grc/gui/Block.py2
-rw-r--r--grc/gui/Colors.py1
-rw-r--r--grc/gui/FlowGraph.py18
-rw-r--r--grc/python/Block.py3
-rw-r--r--grc/python/Generator.py2
-rw-r--r--grc/python/block.dtd5
-rwxr-xr-xgrc/scripts/gnuradio-companion9
225 files changed, 29410 insertions, 2902 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7622d9d5e4..d355b7e801 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,8 +46,8 @@ message(STATUS "Build type set to ${CMAKE_BUILD_TYPE}.")
# Set the version information here
set(VERSION_INFO_MAJOR_VERSION 3)
set(VERSION_INFO_API_COMPAT 7)
-set(VERSION_INFO_MINOR_VERSION 7)
-set(VERSION_INFO_MAINT_VERSION 1)
+set(VERSION_INFO_MINOR_VERSION 8)
+set(VERSION_INFO_MAINT_VERSION git)
include(GrVersion) #setup version info
# Append -O2 optimization flag for Debug builds
@@ -409,6 +409,14 @@ add_subdirectory(gr-zeromq)
if(ENABLE_GR_CTRLPORT)
set(GR_CTRLPORT True)
add_definitions(-DGR_CTRLPORT)
+
+ if(CTRLPORT_BACKENDS GREATER 0)
+ set(GR_RPCSERVER_ENABLED True)
+
+ if(THRIFT_FOUND)
+ set(GR_RPCSERVER_THRIFT True)
+ endif(THRIFT_FOUND)
+ endif(CTRLPORT_BACKENDS GREATER 0)
endif(ENABLE_GR_CTRLPORT)
# Install our Cmake modules into $prefix/lib/cmake/gnuradio
diff --git a/cmake/Modules/FindThrift.cmake b/cmake/Modules/FindThrift.cmake
new file mode 100644
index 0000000000..f12bce01e6
--- /dev/null
+++ b/cmake/Modules/FindThrift.cmake
@@ -0,0 +1,79 @@
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PC_THRIFT thrift)
+
+set(THRIFT_REQ_VERSION "0.9.2")
+
+# If pkg-config found Thrift and it doesn't meet our version
+# requirement, warn and exit -- does not cause an error; just doesn't
+# enable Thrift.
+if(PC_THRIFT_FOUND AND PC_THRIFT_VERSION VERSION_LESS ${THRIFT_REQ_VERSION})
+ message(STATUS "Could not find appropriate version of Thrift: ${PC_THRIFT_VERSION} < ${THRIFT_REQ_VERSION}")
+ return()
+endif(PC_THRIFT_FOUND AND PC_THRIFT_VERSION VERSION_LESS ${THRIFT_REQ_VERSION})
+
+
+# Else, look for it ourselves
+
+FIND_PATH(THRIFT_INCLUDE_DIRS
+ NAMES thrift/Thrift.h
+ HINTS ${PC_THRIFT_INCLUDE_DIR}
+ ${CMAKE_INSTALL_PREFIX}/include
+ PATHS
+ /usr/local/include
+ /usr/include
+ )
+
+FIND_LIBRARY(THRIFT_LIBRARIES
+ NAMES thrift
+ HINTS ${PC_THRIFT_LIBDIR}
+ ${CMAKE_INSTALL_PREFIX}/lib
+ ${CMAKE_INSTALL_PREFIX}/lib64
+ PATHS
+ ${THRIFT_INCLUDE_DIRS}/../lib
+ /usr/local/lib
+ /usr/lib
+ )
+
+# Get the thrift binary to build our files during cmake
+FIND_PROGRAM(THRIFT_BIN thrift)
+
+# Use binary to get version string and test against THRIFT_REQ_VERSION
+EXECUTE_PROCESS(
+ COMMAND ${THRIFT_BIN} --version
+ OUTPUT_VARIABLE THRIFT_VERSION
+ ERROR_VARIABLE THRIFT_VERSION_ERROR
+ )
+
+if(NOT THRIFT_BIN)
+ message(STATUS "Binary 'thrift' not found.")
+ return()
+endif(NOT THRIFT_BIN)
+
+STRING(REGEX MATCH "[0-9]+.[0-9]+.[0-9]+"
+ THRIFT_VERSION "${THRIFT_VERSION}")
+
+if(THRIFT_VERSION VERSION_LESS THRIFT_REQ_VERSION)
+ message(STATUS "Could not find appropriate version of Thrift: ${THRIFT_VERSION} < ${THRIFT_REQ_VERSION}")
+ return()
+endif(THRIFT_VERSION VERSION_LESS THRIFT_REQ_VERSION)
+
+
+# Check that Thrift for Python is available
+include(GrPython)
+GR_PYTHON_CHECK_MODULE("Thrift" thrift "1" PYTHON_THRIFT_FOUND)
+
+# Set to found if we've made it this far
+if(THRIFT_INCLUDE_DIRS AND THRIFT_LIBRARIES AND PYTHON_THRIFT_FOUND)
+ set(THRIFT_FOUND TRUE CACHE BOOL "If Thift has been found")
+endif(THRIFT_INCLUDE_DIRS AND THRIFT_LIBRARIES AND PYTHON_THRIFT_FOUND)
+
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(THRIFT DEFAULT_MSG
+ THRIFT_LIBRARIES THRIFT_INCLUDE_DIRS
+ THRIFT_BIN PYTHON_THRIFT_FOUND THRIFT_FOUND
+)
+MARK_AS_ADVANCED(
+ THRIFT_LIBRARIES THRIFT_INCLUDE_DIRS
+ THRIFT_BIN PYTHON_THRIFT_FOUND THRIFT_FOUND
+)
diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake
index abf4dc4612..ef3a76eb4c 100644
--- a/cmake/Modules/GrSwig.cmake
+++ b/cmake/Modules/GrSwig.cmake
@@ -105,17 +105,36 @@ endfunction(GR_SWIG_MAKE_DOCS)
macro(GR_SWIG_MAKE name)
set(ifiles ${ARGN})
- # Shimming this in here to take care of a SWIG bug with handling
- # vector<size_t> and vector<unsigned int> (on 32-bit machines) and
- # vector<long unsigned int> (on 64-bit machines). Use this to test
- # the size of size_t, then set SIZE_T_32 if it's a 32-bit machine
- # or not if it's 64-bit. The logic in gr_type.i handles the rest.
- INCLUDE(CheckTypeSize)
- CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
- CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
- if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
- list(APPEND GR_SWIG_FLAGS -DSIZE_T_32)
- endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
+ # Take care of a SWIG < 3.0 bug with handling std::vector<size_t>,
+ # by mapping to the correct sized type on the runtime system, one
+ # of "unsigned int", "unsigned long", or "unsigned long long".
+ # Compare the sizeof(size_t) with the sizeof the other types, and
+ # pick the first one in the list with the same sizeof. The logic
+ # in gnuradio-runtime/swig/gr_types.i handles the rest. It is
+ # probably not necessary to do this assignment all of the time,
+ # but it's easier to do it this way than to figure out the
+ # conditions when it is necessary -- and doing it this way won't
+ # hurt. This bug seems to have been fixed with SWIG >= 3.0, and
+ # mostly happens when not doing a native build (e.g., on Mac OS X
+ # when using a 64-bit CPU but building for 32-bit).
+
+ if(SWIG_VERSION VERSION_LESS "3.0.0")
+ include(CheckTypeSize)
+ check_type_size("size_t" SIZEOF_SIZE_T)
+ check_type_size("unsigned int" SIZEOF_UINT)
+ check_type_size("unsigned long" SIZEOF_UL)
+ check_type_size("unsigned long long" SIZEOF_ULL)
+
+ if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
+ list(APPEND GR_SWIG_FLAGS -DSIZE_T_UINT)
+ elseif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UL})
+ list(APPEND GR_SWIG_FLAGS -DSIZE_T_UL)
+ elseif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_ULL})
+ list(APPEND GR_SWIG_FLAGS -DSIZE_T_ULL)
+ else()
+ message(FATAL_ERROR "GrSwig: Unable to find replace for std::vector<size_t>; this should never happen!")
+ endif()
+ endif()
#do swig doc generation if specified
if(GR_SWIG_DOC_FILE)
diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake
index 62caab4b51..ff78ed2726 100644
--- a/cmake/Modules/GrTest.cmake
+++ b/cmake/Modules/GrTest.cmake
@@ -66,7 +66,8 @@ function(GR_ADD_TEST test_name)
file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list?
file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
- set(environs "VOLK_GENERIC=1" "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
+ set(environs "VOLK_GENERIC=1" "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}"
+ "GR_CONF_CONTROLPORT_ON=False")
list(APPEND environs ${GR_TEST_ENVIRONS})
#http://www.cmake.org/pipermail/cmake/2009-May/029464.html
diff --git a/config.h.in b/config.h.in
index 82751a3cf7..ad6e3d022c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -30,6 +30,12 @@
#ifndef GR_CTRLPORT
#cmakedefine GR_CTRLPORT
#endif
+#ifndef GR_RPCSERVER_ENABLED
+#cmakedefine GR_RPCSERVER_ENABLED
+#endif
+#ifndef GR_RPCSERVER_THRIFT
+#cmakedefine GR_RPCSERVER_THRIFT
+#endif
#ifndef ENABLE_GR_LOG
#cmakedefine ENABLE_GR_LOG
#endif
diff --git a/docs/doxygen/other/build_guide.dox b/docs/doxygen/other/build_guide.dox
index 56bcce7f96..8fc3f911fb 100644
--- a/docs/doxygen/other/build_guide.dox
+++ b/docs/doxygen/other/build_guide.dox
@@ -63,7 +63,7 @@ first. Most recent systems have these packages available.
\li audio-osx
\li audio-windows
-* Optional but recommended dependencies.
+<b>Optional but recommended dependencies.</b>
It is not necessary to satisfy all of these dependencies; just the
one(s) that are right for your system. On Linux, don't expect
@@ -82,6 +82,17 @@ audio-osx and audio-windows to be either satisfied or built.
\li log4cpp (>= 1.0) http://log4cpp.sourceforge.net/
+<b>Optional</b>
+
+\ref page_ctrlport may use various backends to perform the RPC
+process, and each is its own dependency.
+
+Currently, ControlPort only supports the Apache Thrift backend.
+
+\li thrift (>= 0.9.2) https://thrift.apache.org/
+
+
+
\section build_gr_cmake Building GNU Radio
GNU Radio is built using the CMake build system
diff --git a/docs/doxygen/other/ctrlport.dox b/docs/doxygen/other/ctrlport.dox
index 64bf9f7d38..94a768e429 100644
--- a/docs/doxygen/other/ctrlport.dox
+++ b/docs/doxygen/other/ctrlport.dox
@@ -16,8 +16,427 @@ gnuradio.ctrlport module, imported as:
from gnuradio import ctrlport
\endcode
-ControlPort is currently a temporary stub implementation of a set of
-RPC calls we would like to enable that would allow remote viewing,
-command, and control of GNU Radio flowgraphs and blocks.
+
+\section ctrlport_conf Configuration
+
+ControlPort is configured using two files. The first is the GNU Radio
+preferences file while the second file is specific to the type of
+middleware used.
+
+The GNU Radio preferences file has three options. The 'on' option is
+used to enable or disable the use of ControlPort, and is disabled by
+default. The 'config' option allows a user to specify the
+middleware-specific configuration file. The 'edges_list' is a special
+option that exports the list of nodes and edges of the flowgraph
+across ControlPort. This latter option is mainly used for redrawing
+the flowgraph for the Performance Counter applications.
+
+\code
+ [ControlPort]
+ on = True
+ edges_list = True
+ config = path-to/ctrlport.conf
+\endcode
+
+The ControlPort preferences are installed by default into
+'gnuradio-runtime.conf'. These can always be overridden in the local
+~/.gnuradio/config.conf file.
+
+
+
+\section ctrlport_deps Dependencies
+
+ControlPort is an abstracted remote procedure call tool that. It is
+built on top of other middleware libraries. The following subsections
+explain some details about the use of the particular middleware
+project.
+
+Currently, the only implemented middleware library is the Apache
+Thrift project.
+
+\subsection ctrlport_thrift Apache Thrift
+
+Current version support: >= 0.9.2
+
+Apache Thrift is a middleware layer that defines interfaces of a
+program using its own Thrift language. GNU Radio's interface file is:
+
+gnuradio-runtime/lib/controlport/thrift/gnuradio.thrift
+
+This file defines the interfaces set, get, trigger, and properties. It
+also defines a set of data structure Knobs to allow us to pass any
+type of data over the interfaces.
+
+To use Thrift in ControlPort requires a minimum Thrift version of
+0.9.0. If a Thrift version greater than or equal to this version is
+not found, the Thrift backend to ControlPort will not be installed,
+through ControlPort itself still will be. During cmake configuration
+time, it prints out information about finding Thrift and requires:
+
+\li Thrift header files by looking for thrift/Thrift.h
+\li Thrift C++ libraries: libthrift.so
+\li Thrift Python bindings: "import thrift"
+
+If all of these are not satisfied, the Thrift backend will not be
+installed. Upon completion, cmake outputs a notification of what
+components will be built. You will see this if Thrift was found and
+can be used:
+
+\code
+* gr-ctrlport
+* * thrift
+\endcode
+
+Cmake also uses the Thrift compiler ("thrift") to build the C++ and
+Python files necessary for compiling ControlPort. It runs "thrift
+--gen cpp" the C++ bindings in the build directory, and then
+it runs "thrift --gen py" to build the Python bindings, also in the
+build directory. These are used to compile the Thrift ControlPort
+features and are necessary files to run the Python clients. If cmake
+fails to produce these bindings, it should error out.
+
+
+
+\subsubsection ctrlport_thrift_prefs Configuration
+
+Thrift does not support its own concept of a configuration file, so we
+have built one for our purposes in GNU Radio. The 'config' option in
+the ControlPort section of the preference files tells ControlPort
+where to find the backend-specific file format. GNU Radio's Thrift
+format follows the same "[Section] key = value" scheme used in all of
+its other preference files. Currently supported configuration options
+are:
+
+\code
+[thrift]
+port = 9090
+nthreads = 2
+buffersize = 1434
+init_attempts = 100
+\endcode
+
+
+\subsubsection ctrlport_thrift_issues Thrift: Current Issues
+
+Thrift uses a thread pool system to handle each connection, but it
+will only allow up to a specified number of threads in the server. The
+default value is 10 threads, but the Thrift configuration file allows
+the user to change this value.
+
+Thrift also does not find and use a free ephemeral port when launching
+the server. It must be told explicitly which port to launch on, which
+we set in the configuration file. This makes it difficult to launch
+multiple flowgraphs on the same machine because that will cause a port
+collision. Until this is fixed, a way around this is to use the
+environmental variable GR_CONF_THRIFT_PORT=xxx to set the port number
+for that specific application.
+
+Efficiency issues of Thrift come from the over-the-wire formatting
+done by the transport protocol. It defaults to using 512 byte packets,
+which can lead to a lot of fragmentation of the data over the
+connection. The buffersize configuration allows the user to set this
+value to whatever number fits their network needs. The default 1434 is
+designed around the standard 1500 byte Ethernet frame size limit minus
+the TCP/IP and Ethernet header size.
+
+
+\subsection ctrlport_client_translation Translation Layer for Clients
+
+Different backends will produce different ways to interface with the
+system. ControlPort in the running flowgraph acts as the server by
+exposing interfaces to blocks. The interfaces and API in GNU Radio to
+communicate with ControlPort are all abstracted completely away from
+the backend methods and data types. That is, the code in GNU Radio's
+scheduler and in the blocks that expose their ControlPort interfaces
+will work regardless of the backend used.
+
+We are building better abstractions on the clients sides now, as
+well. Although certain backends will support other features of
+discovery and services that work well with their products, GNU Radio
+wants to make sure that clients can access the data from the
+interfaces in the same way for any backend used. This abstraction is
+done through the GNURadioControlPortClient. This class is told which
+type of backend is used, and defaults to Thrift, and can be passed
+information about the server's endpoint such as the host name and port
+number to attach to. The GNURadioControlPortClient returns a 'radio'
+object that represents the connection to the running flowgraph.
+
+
+\section ctrlport_using Using ControlPort to Export Variables
+
+The ability to export variables from a block is inherited from
+gr::block. Then, when the flowgraph is started, the function
+<b>setup_rpc()</b> is called in turn for each block. By default, this
+is an empty function. A block overloads this function and defines and
+exports variables in it.
+
+Say we have a class <b>gr::blocks::foo</b> that has variables <b>a</b>
+and <b>b</b> that we want to export. Specifically, we want to be able
+to read the values of both <b>a</b> and <b>b</b> and also set the
+value of <b>b</b>. The class <b>gr::blocks::foo</b> has setters and
+getters all set up. So our class implementation header file looks
+something like:
+
+\code
+namespace gr {
+ namespace blocks {
+
+ class foo_impl : public foo
+ {
+ private:
+ float d_a, d_b;
+
+ public:
+ foo_impl(float a, float b);
+ ~foo_impl();
+
+ float a() const { return d_a; }
+ float b() const { return d_a; }
+ void set_a(float a) { d_a = a; }
+ void set_b(float b) { d_b = b; }
+ void setup_rpc();
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } /* namespace blocks */
+} /* namespace gr */
+\endcode
+
+The source code then sets up the class and fills in
+<b>setup_rpc()</b>.
+
+\code
+namespace gr {
+ namespace blocks {
+
+ foo_impl::foo_impl(float a, float b):
+ sync_bloc(....),
+ d_a(a), d_b(b)
+ { }
+
+ foo_impl::~foo_impl()
+ { }
+
+ void
+ foo_impl::setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<foo, float>(
+ alias(), "a",
+ &foo::a,
+ pmt::mp(-2.0f), pmt::mp(2.0f), pmt::mp(0.0f),
+ "", "Get value of a", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<foo, float>(
+ alias(), "b",
+ &foo::b,
+ pmt::mp(0.0f), pmt::mp(20.0f), pmt::mp(10.0f),
+ "", "Get value of b", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<foo, float>(
+ alias(), "b",
+ &foo::set_b,
+ pmt::mp(0.0f), pmt::mp(20.0f), pmt::mp(10.0f),
+ "", "Set value of b", RPC_PRIVLVL_MIN,
+ DISPNULL)));
+#endif /* GR_CTRLPORT */
+ }
+
+ int
+ foo_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ { .... }
+
+ } /* namespace blocks */
+} /* namespace gr */
+\endcode
+
+In the above example, we're ignoring some of the basic semantics of
+the class as a GNU Radio block and focus just on the call to set up
+the get and set functions over ControlPort. Each block has a function
+that allows us to add a new ControlPort interface object to a list,
+the <b>add_rpc_variable</b>. We don't care about that list anymore;
+that's for ControlPort to worry about. We just add new variables,
+either setters or getters.
+
+Without dissecting every piece of the above calls, notice that we use
+the public class, <b>gr::blocks::foo</b> as the class, not the
+implementation class. We also use the block's alias, which GNU Radio
+uses as a database entry to connect a block by name to the pointer in
+memory. This allows ControlPort to know where the object in memory is
+at any given time to access the setters and getters.
+
+The three PMTs specified are simply an expected minimum, maximum, and
+default value. None of these are strictly enforced and only serve as
+guides. The RPC_PRIVLVL_MIN is currently a placeholder for a
+privilege level setting. In many cases, reading <b>b</b> might be
+fine for everyone, but we want strong restrictions on who has the
+ability to set <b>b</b>.
+
+And finally, we can specify display options to hint at the right way
+to display this variable when remotely plotting it. More on that in
+the following section.
+
+Finally, note that we put \#ifdefs around the code. We always want
+<b>setup_rpc</b> to be there and callable, but if ControlPort was not
+built for GNU Radio, we cannot register any variables with it. This is
+just a nicety to allow us to set up our code for use with ControlPort
+without requiring it.
+
+
+\subsection ctrlport_alt_reg Alternative Registers
+
+If using the concept above, <b>setup_rpc</b> automatically gets called
+when the flowgraph is started. In most instances, this is all we ever
+need since there's nothing interesting going on until then. However,
+if not using a gr::block or needing access before we run the flowgraph,
+the above method won't work (it comes down to when the block's alias
+has meaning).
+
+There are alternate variable registration functions for the sets and
+gets. These take the form:
+
+\code
+ rpcbasic_register_get(const std::string& name,
+ const char* functionbase,
+ T* obj,
+ Tfrom (T::*function)(),
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+
+ rpcbasic_register_set(const std::string& name,
+ const char* functionbase,
+ T* obj,
+ void (T::*function)(Tto),
+ const pmt::pmt_t &min, const pmt::pmt_t &max, const pmt::pmt_t &def,
+ const char* units_ = "",
+ const char* desc_ = "",
+ priv_lvl_t minpriv_ = RPC_PRIVLVL_MIN,
+ DisplayType display_ = DISPNULL)
+\endcode
+
+The only thing different about the above code is that instead of
+taking a single 'alias()' name, which provides us access to the
+objects pointer, we instead provide a unique name
+(<b>fucntionbase</b>) and a pointer to the object itself
+(<b>obj</b>). These are templated functions, so the class T is known
+from that.
+
+If using this method, the recommended way is to create a new function
+(not <b>setup_rpc</b>), register the variable using
+<b>add_rpc_variable</b> but with the different <b>register_get/set</b>
+shown here, and then call this function either in the object's
+constructor or make it a public member function to be called when you
+need it.
+
+
+\section ctrlport_disp Display Options
+
+When exporting a new RPC variable over ControlPort, one argument is a
+display options mask. These options are useful to a remote client to
+tell identify activities like default plotters and initial
+conditions. The <b>gr-ctrlport-monitor</b> application uses this
+heavily in determining how to plot ControlPort variables.
+
+The options mask is just a 32-bit value with options OR'd
+together. Certain options are only appropriate for certain types of
+plots. Options on plots where that option is not available will
+simply be ignored.
+
+The main caveat to be aware of is that the DISPXY plot type is
+specific to complex values. Therefore, DISPOPTCPLX is assumed.
+
+These options are specified in rpccallbackregister_base.h and are
+exposed through SWIG to live in the \b gr namespace.
+
+<b>Plot Types</b>
+\li <b>DISPNULL:</b> Nothing specified.
+\li <b>DISPTIME:</b> Time-domain plot.
+\li <b>DISPXY:</b> XY or constellation plot (complex only).
+\li <b>DISPPSD:</b> PSD plot.
+\li <b>DISPSPEC:</b> Spectrogram plot.
+\li <b>DISPRAST:</b> Time raster plot (non-complex only)
+
+<b>Plot Options</b>
+\li <b>DISPOPTCPLX:</b> Signal is complex.
+\li <b>DISPOPTLOG:</b> Start plot in semilog-y mode (time domain only).
+\li <b>DISPOPTSTEM:</b> Start plot in stem mode (time domain only).
+\li <b>DISPOPTSTRIP:</b> Run plot as a stripchart (time domain only).
+\li <b>DISPOPTSCATTER:</b> Do scatter plot instead of lines (XY plot only).
+
+
+\section ctrlport_probes ControlPort Probes
+
+ControlPort provides a set of probes that can be used as sinks that
+pass vectors of data across ControlPort. These probes are used to
+sample or visualize data remotely. We can place a ControlPort probe
+anywhere in the flowgraph to grab the latest sample of data from the
+block it's connected to.
+
+The main ControlPort probe to use is
+<b>blocks.ctrlport_probe2_x</b>. From GRC, this is simply "CtrlPort
+Probe", which can handle complex, floats, ints, shorts, and bytes. The
+blocks are named and given a description to identify them over
+ControlPort. The blocks also take a vector length for how many samples
+to pass back at a time. Finally, these blocks take a display hint,
+as described in the above section. This allows us to specify the
+default behavior for how to display the samples.
+
+Another block that can be used is the <b>fft.ctrlport_probe_psd</b> to
+calculate the PSD and pass that over the ControlPort interface.
+
+\section ctrlport_monitors ControlPort Monitors
+
+There are two main ControlPort monitor applications provided with GNU
+Radio. Both act similarly. The first is a standard ControlPort monitor
+application. This connects to a running flowgraph and displays all
+exported interfaces in a table format. The name, unit, latest sample,
+and description of all interfaces are display in a
+row. Double-clicking will open up the default display. Right clicking
+any item will allow the user to select the type of plot to use to
+display the data.
+
+When a display is active, using the buttons at the top, the subwindows
+can all be tiled or windowed as needed to manage the full
+interface. We can then drag-and-drop any other item on top of a
+currently running display plot.
+
+To launch the ControlPort monitor application, know the IP address and
+port of the ControlPort endpoint established by the flowgraph and run:
+
+<pre>
+gr-ctrlport-monitor \<ip-addr\> -p \<port\>
+</pre>
+
+
+\subsection perfmonitor Performance Monitor
+
+A second application is used to locally redraw the flowgraph and
+display some of the Performance Counters. In this application, the
+nodes are blue boxes where the size of the box is proportional to the
+work time and the color depth and line width are proportional to the
+output buffer fullness.
+
+The controls at the top of the Performance Monitor application allow
+us to select the instantaneous, average, and variance values of the
+Performance Counters. And the work time and buffer fullness can be
+displayed as a table or bar graph.
+
+To launch the Performance Monitor, run:
+
+<pre>
+gr-perf-monitorx \<ip-addr\> -p \<port\>
+</pre>
*/
diff --git a/docs/doxygen/other/perf_counters.dox b/docs/doxygen/other/perf_counters.dox
index 1a5bf40cba..9bca38268a 100644
--- a/docs/doxygen/other/perf_counters.dox
+++ b/docs/doxygen/other/perf_counters.dox
@@ -85,4 +85,14 @@ The options for the [PerfCounters] section are:
\li clock: sets the type of clock used when calculating work_time
('thread' or 'monotonic').
+
+\section pc_perfmonitor Performance Monitor
+
+See \ref perfmonitor for some details of using a ControlPort-based
+monitor application, gr-perf-monitorx, for visualizing the
+counters. This application is particularly useful in learning which
+blocks are the computationally complex blocks that could use extra
+optimization or work to improve their performance. It can also be used
+to understand the current 'health' of the application.
+
*/
diff --git a/gnuradio-runtime/include/gnuradio/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/CMakeLists.txt
index 3fc2fe7bd8..472f91847b 100644
--- a/gnuradio-runtime/include/gnuradio/CMakeLists.txt
+++ b/gnuradio-runtime/include/gnuradio/CMakeLists.txt
@@ -86,6 +86,16 @@ install(FILES
COMPONENT "runtime_devel"
)
+if(THRIFT_FOUND)
+install(FILES
+ rpcserver_booter_thrift.h
+ thrift_application_base.h
+ thrift_server_template.h
+ DESTINATION ${GR_INCLUDE_DIR}/gnuradio
+ COMPONENT "runtime_devel"
+)
+endif(THRIFT_FOUND)
+
##########################################################################
# Configure logger
##########################################################################
diff --git a/gnuradio-runtime/include/gnuradio/prefs.h b/gnuradio-runtime/include/gnuradio/prefs.h
index a9a28586ab..4dc92b3631 100644
--- a/gnuradio-runtime/include/gnuradio/prefs.h
+++ b/gnuradio-runtime/include/gnuradio/prefs.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006,2013 Free Software Foundation, Inc.
+ * Copyright 2006,2013,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -47,10 +47,38 @@ namespace gr {
public:
static prefs *singleton();
+ /*!
+ * \brief Creates an object to read preference files.
+ *
+ * \details
+ *
+ * If no file name is given (empty arg list or ""), this opens up
+ * the standard GNU Radio configuration files in
+ * prefix/etc/gnuradio/conf.d as well as ~/.gnuradio/config.conf.
+ *
+ * Only access this through the singleton defined here:
+ * \code
+ * prefs *p = prefs::singleton();
+ * \endcode
+ */
prefs();
+
virtual ~prefs();
/*!
+ * If specifying a file name, this opens that specific
+ * configuration file of the standard form containing sections and
+ * key-value pairs:
+ *
+ * \code
+ * [SectionName]
+ * key0 = value0
+ * key1 = value1
+ * \endcode
+ */
+ void add_config_file(const std::string &configfile);
+
+ /*!
* \brief Returns the configuration options as a string.
*/
std::string to_string();
@@ -137,7 +165,7 @@ namespace gr {
protected:
virtual std::vector<std::string> _sys_prefs_filenames();
- virtual void _read_files();
+ virtual std::string _read_files(const std::vector<std::string> &filenames);
virtual void _convert_to_map(const std::string &conf);
virtual char * option_to_env(std::string section, std::string option);
diff --git a/gnuradio-runtime/include/gnuradio/rpcbufferedget.h b/gnuradio-runtime/include/gnuradio/rpcbufferedget.h
new file mode 100644
index 0000000000..ad05551d1a
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/rpcbufferedget.h
@@ -0,0 +1,64 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RPCBUFFEREDGET_H
+#define RPCBUFFEREDGET_H
+
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/mutex.hpp>
+
+template<typename TdataType>
+class rpcbufferedget {
+public:
+ rpcbufferedget(const unsigned int init_buffer_size = 4096) :
+ d_data_needed(false), d_data_ready(), d_buffer_lock(), d_buffer(init_buffer_size) {;}
+
+ ~rpcbufferedget() {
+ d_data_ready.notify_all();
+ }
+
+ void offer_data(const TdataType& data) {
+ if (!d_data_needed)
+ return;
+ {
+ boost::mutex::scoped_lock lock(d_buffer_lock);
+ d_buffer = data;
+ d_data_needed = false;
+ }
+ d_data_ready.notify_one();
+ }
+
+ TdataType get() {
+ boost::mutex::scoped_lock lock(d_buffer_lock);
+ d_data_needed = true;
+ d_data_ready.wait(lock);
+ return d_buffer;
+ }
+
+private:
+ bool d_data_needed;
+ boost::condition_variable d_data_ready;
+ boost::mutex d_buffer_lock;
+ TdataType d_buffer;
+};
+
+#endif
diff --git a/gnuradio-runtime/include/gnuradio/rpcmanager.h b/gnuradio-runtime/include/gnuradio/rpcmanager.h
index 5635572a8b..e7ee4c4942 100644
--- a/gnuradio-runtime/include/gnuradio/rpcmanager.h
+++ b/gnuradio-runtime/include/gnuradio/rpcmanager.h
@@ -54,7 +54,7 @@ class GR_RUNTIME_API rpcmanager : public virtual rpcmanager_base
static bool booter_registered;
static bool aggregator_registered;
static void rpcserver_booter_base_sptr_dest(rpcserver_booter_base* b) {;}
- static rpcserver_booter_base* boot;
+ static std::auto_ptr<rpcserver_booter_base> boot;
static std::auto_ptr<rpcserver_booter_aggregator> aggregator;
};
diff --git a/gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h b/gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h
new file mode 100644
index 0000000000..d55e7eb3b9
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/rpcpmtconverters_thrift.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014,2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RPCPMTCONVERTERS_THRIFT_H
+#define RPCPMTCONVERTERS_THRIFT_H
+
+#include <pmt/pmt.h>
+#include <boost/noncopyable.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
+#include "thrift/gnuradio_types.h"
+
+
+namespace rpcpmtconverter
+{
+ GNURadio::Knob from_pmt(const pmt::pmt_t& knob);
+
+ struct to_pmt_f {
+ to_pmt_f() {;}
+ virtual ~to_pmt_f() {}
+ virtual pmt::pmt_t operator()(const GNURadio::Knob& knob);
+ };
+
+ struct to_pmt_byte_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_short_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_int_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_long_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_double_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_string_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_bool_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_complex_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_f32vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_f64vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_s64vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_s32vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_s16vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_s8vect_f : public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+ struct to_pmt_c32vect_f: public to_pmt_f { pmt::pmt_t operator()(const GNURadio::Knob& knob); };
+
+ class To_PMT : private boost::noncopyable {
+ public:
+ static To_PMT instance;
+ template<typename TO_PMT_F> friend struct to_pmt_reg;
+ pmt::pmt_t operator()(const GNURadio::Knob& knob);
+
+ protected:
+ boost::ptr_map<GNURadio::BaseTypes::type, to_pmt_f> to_pmt_map;
+
+ private:
+ To_PMT() {;}
+ };
+
+ template<typename TO_PMT_F> struct to_pmt_reg {
+ to_pmt_reg(To_PMT& instance, const GNURadio::BaseTypes::type type);
+ };
+}
+
+#endif /* RPCPMTCONVERTERS_THRIFT_H */
diff --git a/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h
index 0999dea747..f82f5ed0aa 100644
--- a/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h
+++ b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h
@@ -672,7 +672,7 @@ struct rpcbasic_register_set : public rpcbasic_base
d_minpriv = minpriv_;
d_display = display_;
d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::configureCallback_t
extractor(new rpcbasic_extractor<T,Tto>(d_object, function),
minpriv_, std::string(units_),
@@ -726,7 +726,7 @@ struct rpcbasic_register_set : public rpcbasic_base
d_minpriv = minpriv_;
d_display = display_;
d_object = obj;
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::configureCallback_t
extractor(new rpcbasic_extractor<T,Tto>(d_object, function),
minpriv_, std::string(units_),
@@ -741,7 +741,7 @@ struct rpcbasic_register_set : public rpcbasic_base
~rpcbasic_register_set()
{
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
rpcmanager::get()->i()->unregisterConfigureCallback(d_id);
#endif
}
@@ -830,7 +830,7 @@ struct rpcbasic_register_trigger : public rpcbasic_base
d_desc = desc_;
d_minpriv = minpriv_;
d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::configureCallback_t
extractor(new rpcbasic_extractor<T,void>(d_object, function),
minpriv_, std::string(desc_));
@@ -870,7 +870,7 @@ struct rpcbasic_register_trigger : public rpcbasic_base
d_desc = desc_;
d_minpriv = minpriv_;
d_object = obj;
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::configureCallback_t
extractor(new rpcbasic_extractor<T,void>(d_object, function),
minpriv_, std::string(desc_));
@@ -884,7 +884,7 @@ struct rpcbasic_register_trigger : public rpcbasic_base
~rpcbasic_register_trigger()
{
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
rpcmanager::get()->i()->unregisterConfigureCallback(d_id);
#endif
}
@@ -988,7 +988,7 @@ public:
d_minpriv = minpriv_;
d_display = display_;
d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::queryCallback_t
inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function),
minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
@@ -1022,7 +1022,7 @@ public:
d_minpriv = minpriv_;
d_display = display_;
d_object = dynamic_cast<T*>(global_block_registry.block_lookup(pmt::intern(block_alias)).get());
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::queryCallback_t
inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function),
minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
@@ -1076,7 +1076,7 @@ public:
d_minpriv = minpriv_;
d_display = display_;
d_object = obj;
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::queryCallback_t
inserter(new rpcbasic_inserter<T,Tfrom>(d_object, function),
minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
@@ -1111,7 +1111,7 @@ public:
d_minpriv = minpriv_;
d_display = display_;
d_object = obj;
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
callbackregister_base::queryCallback_t
inserter(new rpcbasic_inserter<T,Tfrom>(d_object, (Tfrom (T::*)())function),
minpriv_, std::string(units_), display_, std::string(desc_), min, max, def);
@@ -1125,7 +1125,7 @@ public:
~rpcbasic_register_get()
{
-#ifdef RPCSERVER_ENABLED
+#ifdef GR_RPCSERVER_ENABLED
rpcmanager::get()->i()->unregisterQueryCallback(d_id);
#endif
}
diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h b/gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h
new file mode 100644
index 0000000000..fd1da09fa6
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/rpcserver_booter_thrift.h
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RPCSERVER_BOOTER_THRIFT_H
+#define RPCSERVER_BOOTER_THRIFT_H
+
+#include <gnuradio/rpcserver_booter_base.h>
+#include <gnuradio/thrift_server_template.h>
+#include "thrift/ControlPort.h"
+
+class rpcserver_base;
+class rpcserver_thrift;
+
+class rpcserver_booter_thrift
+ : public virtual rpcserver_booter_base,
+ public virtual thrift_server_template<rpcserver_base,
+ rpcserver_thrift,
+ rpcserver_booter_thrift>
+{
+ public:
+ rpcserver_booter_thrift();
+ ~rpcserver_booter_thrift();
+
+ rpcserver_base* i();
+ const std::string & type() {return d_type;}
+ const std::vector<std::string> endpoints();
+
+ private:
+ std::string d_type;
+};
+
+#endif /* RPCSERVER_BOOTER_THRIFT_H */
diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_selector.h b/gnuradio-runtime/include/gnuradio/rpcserver_selector.h
index 8a14f78d99..31ab6cea0b 100644
--- a/gnuradio-runtime/include/gnuradio/rpcserver_selector.h
+++ b/gnuradio-runtime/include/gnuradio/rpcserver_selector.h
@@ -23,10 +23,12 @@
#ifndef RPCSERVER_SELECTOR
#define RPCSERVER_SELECTOR
-//#define RPCSERVER_ENABLED
+#include <gnuradio/config.h>
-//#define RPCSERVER_ICE
-//#define RPCSERVER_ERLANG
-//#define RPCSERVER_XMLRPC
+//#define GR_RPCSERVER_ENABLED
+//#define GR_RPCSERVER_ICE
+//#define GR_RPCSERVER_THRIFT
+//#define GR_RPCSERVER_ERLANG
+//#define GR_RPCSERVER_XMLRPC
#endif
diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_thrift.h b/gnuradio-runtime/include/gnuradio/rpcserver_thrift.h
new file mode 100644
index 0000000000..203be66e9a
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/rpcserver_thrift.h
@@ -0,0 +1,233 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014,2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef RPCSERVER_THRIFT_H
+#define RPCSERVER_THRIFT_H
+
+#include <gnuradio/rpcserver_base.h>
+#include <gnuradio/rpcpmtconverters_thrift.h>
+#include <string>
+#include <iostream>
+#include <sstream>
+#include <map>
+#include "thrift/ControlPort.h"
+#include "thrift/gnuradio_types.h"
+#include <boost/format.hpp>
+#include <boost/thread/mutex.hpp>
+
+#define S(x) #x
+#define S_(x) S(x)
+#define S__LINE__ S_(__LINE__)
+
+class rpcserver_thrift : public virtual rpcserver_base, public GNURadio::ControlPortIf
+{
+public:
+ rpcserver_thrift();
+ virtual ~rpcserver_thrift();
+
+ void registerConfigureCallback(const std::string &id,
+ const configureCallback_t callback);
+ void unregisterConfigureCallback(const std::string &id);
+
+ void registerQueryCallback(const std::string &id,
+ const queryCallback_t callback);
+ void unregisterQueryCallback(const std::string &id);
+
+ void setKnobs(const GNURadio::KnobMap&);
+ void getKnobs(GNURadio::KnobMap&,
+ const GNURadio::KnobIDList&);
+ void getRe(GNURadio::KnobMap&,
+ const GNURadio::KnobIDList&);
+ void properties(GNURadio::KnobPropMap&,
+ const GNURadio::KnobIDList& knobs);
+ virtual void shutdown();
+
+ private:
+ boost::mutex d_callback_map_lock;
+
+ typedef std::map<std::string, configureCallback_t> ConfigureCallbackMap_t;
+ ConfigureCallbackMap_t d_setcallbackmap;
+
+ typedef std::map<std::string, queryCallback_t> QueryCallbackMap_t;
+ QueryCallbackMap_t d_getcallbackmap;
+
+ template<typename T, typename TMap> struct set_f
+ : public std::unary_function<T,void>
+ {
+ set_f(TMap &_setcallbackmap, const priv_lvl_t &_cur_priv)
+ : d_setcallbackmap(_setcallbackmap), cur_priv(_cur_priv)
+ {
+ ;
+ }
+
+ void operator()(const T& p)
+ {
+ ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(p.first));
+ if(iter != d_setcallbackmap.end()) {
+ if(cur_priv <= iter->second.priv) {
+ (*iter->second.callback).post(pmt::PMT_NIL, rpcpmtconverter::To_PMT::instance(p.second));
+ }
+ else {
+ std::cout << "Key " << p.first << " requires PRIVLVL <= "
+ << iter->second.priv << " to set, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+ else {
+ throw apache::thrift::TApplicationException(__FILE__ " " S__LINE__);
+ }
+ }
+
+ TMap& d_setcallbackmap;
+ const priv_lvl_t& cur_priv;
+ };
+
+ template<typename T, typename TMap>
+ struct get_f : public std::unary_function<T,void>
+ {
+ get_f(TMap &_getcallbackmap, const priv_lvl_t &_cur_priv, GNURadio::KnobMap &_outknobs) :
+ d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {}
+
+ void operator()(const T& p)
+ {
+ QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(p));
+ if(iter != d_getcallbackmap.end()) {
+ if(cur_priv <= iter->second.priv) {
+ outknobs[p] = rpcpmtconverter::from_pmt((*iter->second.callback).retrieve());
+ }
+ else {
+ std::cout << "Key " << iter->first << " requires PRIVLVL: <= "
+ << iter->second.priv << " to get, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+ else {
+ std::stringstream ss;
+ ss << "Ctrlport Key called with unregistered key (" << p << ")\n";
+ std::cout << ss.str();
+ throw apache::thrift::TApplicationException(__FILE__ " " S__LINE__);
+ }
+ }
+
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ GNURadio::KnobMap& outknobs;
+ };
+
+ template<typename T, typename TMap, typename TKnobMap>
+ struct get_all_f : public std::unary_function<T,void>
+ {
+ get_all_f(TMap &_getcallbackmap, const priv_lvl_t &_cur_priv, TKnobMap &_outknobs) :
+ d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {;}
+
+ void operator()(const T& p)
+ {
+ if(cur_priv <= p.second.priv) {
+ outknobs[p.first] = rpcpmtconverter::from_pmt(p.second.callback->retrieve());
+ }
+ else {
+ std::cout << "Key " << p.first << " requires PRIVLVL <= "
+ << p.second.priv << " to get, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ TKnobMap& outknobs;
+ };
+
+ template<typename T, typename TMap, typename TKnobMap>
+ struct properties_all_f : public std::unary_function<T,void>
+ {
+ properties_all_f(QueryCallbackMap_t &_getcallbackmap,
+ const priv_lvl_t &_cur_priv,
+ GNURadio::KnobPropMap &_outknobs)
+ : d_getcallbackmap(_getcallbackmap),
+ cur_priv(_cur_priv),
+ outknobs(_outknobs)
+ {;}
+
+ void operator()(const T& p)
+ {
+ if(cur_priv <= p.second.priv) {
+ GNURadio::KnobProp prop;
+ prop.type = GNURadio::KnobType::KNOBDOUBLE;
+ prop.units = p.second.units;
+ prop.description = p.second.description;
+ prop.min = rpcpmtconverter::from_pmt(p.second.min);
+ prop.max = rpcpmtconverter::from_pmt(p.second.max);
+ prop.display = static_cast<uint32_t>(p.second.display);
+ outknobs[p.first] = prop;
+ }
+ else {
+ std::cout << "Key " << p.first << " requires PRIVLVL <= "
+ << p.second.priv << " to get, currently at: "
+ << cur_priv << std::endl;
+ }
+ }
+
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ TKnobMap& outknobs;
+ };
+
+ template<class T, typename TMap, typename TKnobMap>
+ struct properties_f : public std::unary_function<T,void>
+ {
+ properties_f(TMap &_getcallbackmap, const priv_lvl_t &_cur_priv, TKnobMap &_outknobs) :
+ d_getcallbackmap(_getcallbackmap), cur_priv(_cur_priv), outknobs(_outknobs)
+ {;}
+
+ void operator()(const T& p)
+ {
+ typename TMap::const_iterator iter(d_getcallbackmap.find(p));
+ if(iter != d_getcallbackmap.end()) {
+ if(cur_priv <= iter->second.priv) {
+ GNURadio::KnobProp prop;
+ prop.type = GNURadio::KnobType::KNOBDOUBLE;
+ prop.units = iter->second.units;
+ prop.description = iter->second.description;
+ prop.min = rpcpmtconverter::from_pmt(iter->second.min);
+ prop.max = rpcpmtconverter::from_pmt(iter->second.max);
+ prop.display = static_cast<uint32_t>(iter->second.display);
+ outknobs[p] = prop;
+ }
+ else {
+ std::cout << "Key " << iter->first << " requires PRIVLVL: <= "
+ << iter->second.priv << " to get, currently at: " << cur_priv << std::endl;
+ }
+ }
+ else {
+ throw apache::thrift::TApplicationException(__FILE__ " " S__LINE__);
+ }
+ }
+
+ TMap& d_getcallbackmap;
+ const priv_lvl_t& cur_priv;
+ TKnobMap& outknobs;
+ };
+};
+
+#endif /* RPCSERVER_THRIFT_H */
diff --git a/gnuradio-runtime/include/gnuradio/thrift_application_base.h b/gnuradio-runtime/include/gnuradio/thrift_application_base.h
new file mode 100644
index 0000000000..d58f034a4f
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/thrift_application_base.h
@@ -0,0 +1,252 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef THRIFT_APPLICATION_BASE_H
+#define THRIFT_APPLICATION_BASE_H
+
+#include <gnuradio/api.h>
+#include <gnuradio/logger.h>
+#include <gnuradio/prefs.h>
+#include <gnuradio/thread/thread.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace {
+ // Time, in milliseconds, to wait between checks to the Thrift runtime to see if
+ // it has fully initialized.
+ static const unsigned int THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS(200);
+};
+
+namespace apache { namespace thrift { namespace server { class TServer; } } }
+
+/*!
+ * \brief Class to be statically initialized by thrift_application_base. Used
+ * to store state for thrift_application_base's singleton functions.
+ */
+
+class thrift_application_base_impl
+{
+public:
+ thrift_application_base_impl() :
+ d_application_initilized(false),
+ d_endpointStr(""),
+ d_start_thrift_thread() {;}
+
+ // Used to ensure the Thrift runtime is initialized on the first call to ::i().
+ bool d_application_initilized;
+ // Stores the generated endpoint string after the Thrift runtime has initialized.
+ std::string d_endpointStr;
+ // Thread to execute the Thrift runtime's blocking serve() function.
+ boost::shared_ptr<gr::thread::thread> d_start_thrift_thread;
+};
+
+/*!
+ * \brief Base class for a Thrift application with a singleton with
+ * instance function thrift_application_base::i(). Lazy initialization
+ * is used to start the Thrift runtime, therefore the Thrift runtime
+ * is not started unless thrift_application_base::i() is called at
+ * least once. This typically means that at least one rpc variable
+ * must be registered by a block before the runtime will start.
+ *
+ * \param TserverBase Template parameter naming the type of the server
+ * base, which is typically rpcserverbase.
+ * \param TserverClass Template parameter naming the eventual type of
+ * the fully derived application.
+ * \param _app Reference to the fully derived application instance to
+ * be returned by thrift_application_base::i().
+ */
+
+template<typename TserverBase, typename TserverClass>
+class thrift_application_base
+{
+public:
+ thrift_application_base(TserverClass* _app);
+
+ /*!
+ * Destructor for the application. Since shutdown and cleanup of the
+ * runtime is typically custom to a particular booter
+ * implementation, this must be implemented as a specialized function
+ * for a particular booter. Thus a template implementation is not
+ * provided here.
+ */
+ ~thrift_application_base();
+
+ /*!
+ * The application singleton instance function.
+ */
+ static TserverBase* i();
+
+ /*!
+ * Returns the endpoint string of this application.
+ */
+ static const std::vector<std::string> endpoints();
+
+protected:
+ /*!
+ * Allows this application's booter to set the endpoint string after
+ * the Thrift runtime has initialized.
+ *
+ * \param[in] endpoint The endpoint string reported by this class.
+ */
+ void set_endpoint(const std::string& endpoint);
+
+ virtual TserverBase* i_impl() = 0;
+
+ /*!
+ * Reference to the fully derived application instance.
+ */
+ static TserverClass* d_application;
+
+ /*!
+ * Reference to the Thrift runtime.
+ */
+ boost::scoped_ptr<apache::thrift::server::TServer> d_thriftserver;
+
+ /*!
+ * Max number of attempts when checking the Thrift runtime for
+ * Initialization before giving up. Set in the Thrift config file
+ * (see \ref ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_max_init_attempts;
+
+ /*!
+ * Default port for the runtime to listen on, if a static port is
+ * not specified. Set in the Thrift config file (see \ref
+ * ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_thrift_port;
+
+ /*!
+ * Maximum number of threads to create when serving multiple rpc
+ * clients. Set in the Thrift config file (see \ref
+ * ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_num_thrift_threads;
+
+ /*!
+ * Default packet size for the IP payload of thrift packets. Set in
+ * the Thrift config file (see \ref ctrlport_thrift_prefs).
+ */
+ static const unsigned int d_default_thrift_buffer_size;
+
+ /*!
+ * \ref page_logger instances.
+ */
+ gr::logger_ptr d_logger, d_debug_logger;
+
+private:
+
+ // Function to be called in a separate thread to invoke the blocking
+ // ThriftServer::serve() function. Must be specialized for a particular
+ // booter implementation, therefore a template implementation is
+ // not provided here.
+ void start_thrift();
+
+ // Non-blocking function that returns true when the Thrift
+ // runtime has finished initialization. Must be implemented
+ // as a specialized template function for a particular booter
+ // implementation, therefore template implementation is not
+ // provided here.
+ bool application_started();
+
+ // Internal function to start the initialization of the runtime.
+ // Since this singleton uses lazy instantiation, this function
+ // will be called on the first call to the instance function ::i(),
+ // and since ::i() is static, this function must be static as well.
+ static void start_application();
+
+ // Pointer to the structure containing staticly allocated
+ // state information for the applicaiton_base singleton.
+ static boost::scoped_ptr<thrift_application_base_impl > p_impl;
+
+ // Mutex to protect the endpoint string.
+ gr::thread::mutex d_lock;
+
+ // Will be set to true by a the application_started() function,
+ // specialized for a particular booter implementation, once the
+ // thrift runtime has successfully initialized.
+ bool d_thirft_is_running;
+};
+
+template<typename TserverBase, typename TserverClass>
+TserverClass* thrift_application_base<TserverBase, TserverClass>::d_application(0);
+
+template<typename TserverBase, typename TserverClass>
+thrift_application_base<TserverBase, TserverClass>::thrift_application_base(TserverClass* _app)
+ : d_lock(),
+ d_thirft_is_running(false)
+{
+ gr::configure_default_loggers(d_logger, d_debug_logger, "controlport");
+ d_application = _app;
+}
+
+template<typename TserverBase, typename TserverClass>
+void thrift_application_base<TserverBase, TserverClass>::start_application()
+{
+ unsigned int max_init_attempts = \
+ static_cast<unsigned int>(gr::prefs::singleton()->get_long("thrift", "init_attempts",
+ d_default_max_init_attempts));
+
+ if(!p_impl->d_application_initilized) {
+ p_impl->d_start_thrift_thread.reset(
+ (new gr::thread::thread(boost::bind(&thrift_application_base::start_thrift, d_application))));
+
+ bool app_started(false);
+ for(unsigned int attempts(0); (!app_started && attempts < max_init_attempts); ++attempts) {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(THRIFTAPPLICATION_ACTIVATION_TIMEOUT_MS));
+ app_started = d_application->application_started();
+ }
+
+ if(!app_started) {
+ GR_LOG_WARN(d_logger, "thrift_application_base::start_application(), "
+ "timeout waiting to port number might have failed?");
+ }
+
+ p_impl->d_application_initilized = true;
+ }
+}
+
+template<typename TserverBase, typename TserverClass>
+const std::vector<std::string> thrift_application_base<TserverBase, TserverClass>::endpoints()
+{
+ std::vector<std::string> ep;
+ ep.push_back(p_impl->d_endpointStr);
+ return ep;
+}
+
+template<typename TserverBase, typename TserverClass>
+void thrift_application_base<TserverBase, TserverClass>::set_endpoint(const std::string& endpoint)
+{
+ gr::thread::scoped_lock guard(d_lock);
+ p_impl->d_endpointStr = endpoint;
+}
+
+template<typename TserverBase, typename TserverClass>
+TserverBase* thrift_application_base<TserverBase, TserverClass>::i()
+{
+ if(!p_impl->d_application_initilized) {
+ start_application();
+ }
+ return d_application->i_impl();
+}
+
+#endif
diff --git a/gnuradio-runtime/include/gnuradio/thrift_server_template.h b/gnuradio-runtime/include/gnuradio/thrift_server_template.h
new file mode 100644
index 0000000000..e2d6f63a69
--- /dev/null
+++ b/gnuradio-runtime/include/gnuradio/thrift_server_template.h
@@ -0,0 +1,159 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef THRIFT_SERVER_TEMPLATE_H
+#define THRIFT_SERVER_TEMPLATE_H
+
+#include <gnuradio/prefs.h>
+#include <gnuradio/logger.h>
+#include <gnuradio/rpcserver_thrift.h>
+#include <gnuradio/thrift_application_base.h>
+#include <iostream>
+
+#include <thrift/server/TSimpleServer.h>
+#include <thrift/server/TThreadPoolServer.h>
+#include <thrift/concurrency/ThreadManager.h>
+#include <thrift/concurrency/PlatformThreadFactory.h>
+#include <thrift/transport/TServerSocket.h>
+#include <thrift/transport/TBufferTransports.h>
+#include "thrift/ControlPort.h"
+
+using namespace apache;
+
+template<typename TserverBase, typename TserverClass, typename TImplClass>
+class thrift_server_template : public thrift_application_base<TserverBase, TImplClass>
+{
+public:
+ thrift_server_template(TImplClass* _this);
+ ~thrift_server_template();
+
+protected:
+ TserverBase* i_impl();
+ friend class thrift_application_base<TserverBase, TImplClass>;
+
+private:
+ boost::shared_ptr<TserverClass> d_handler;
+ boost::shared_ptr<thrift::TProcessor> d_processor;
+ boost::shared_ptr<thrift::transport::TServerTransport> d_serverTransport;
+ boost::shared_ptr<thrift::transport::TTransportFactory> d_transportFactory;
+ boost::shared_ptr<thrift::protocol::TProtocolFactory> d_protocolFactory;
+ /**
+ * Custom TransportFactory that allows you to override the default Thrift buffer size
+ * of 512 bytes.
+ *
+ */
+ class TBufferedTransportFactory : public thrift::transport::TTransportFactory
+ {
+ public:
+ TBufferedTransportFactory(const unsigned int _bufferSize) : bufferSize(_bufferSize) {;}
+
+ virtual ~TBufferedTransportFactory() {}
+
+ virtual boost::shared_ptr<thrift::transport::TTransport> getTransport(
+ boost::shared_ptr<thrift::transport::TTransport> trans)
+ {
+ return boost::shared_ptr<thrift::transport::TTransport>
+ (new thrift::transport::TBufferedTransport(trans, bufferSize));
+ }
+ private:
+ unsigned int bufferSize;
+ };
+};
+
+template<typename TserverBase, typename TserverClass, typename TImplClass>
+thrift_server_template<TserverBase, TserverClass, TImplClass>::thrift_server_template(TImplClass* _this)
+ : thrift_application_base<TserverBase, TImplClass>(_this),
+ d_handler(new TserverClass()),
+ d_processor(new GNURadio::ControlPortProcessor(d_handler)),
+ d_serverTransport(),
+ d_transportFactory(),
+ d_protocolFactory(new thrift::protocol::TBinaryProtocolFactory())
+{
+ gr::logger_ptr logger, debug_logger;
+ gr::configure_default_loggers(logger, debug_logger, "controlport");
+
+ unsigned int port, nthreads, buffersize;
+ std::string thrift_config_file = gr::prefs::singleton()->get_string("ControlPort", "config", "");
+
+ if(thrift_config_file.length() > 0) {
+ gr::prefs::singleton()->add_config_file(thrift_config_file);
+ }
+
+ // Collect configuration options from the Thrift config file;
+ // defaults if the config file doesn't exist or list the specific
+ // options.
+ port = static_cast<unsigned int>
+ (gr::prefs::singleton()->get_long("thrift", "port",
+ thrift_application_base<TserverBase,
+ TImplClass>::d_default_thrift_port));
+ nthreads = static_cast<unsigned int>
+ (gr::prefs::singleton()->get_long("thrift", "nthreads",
+ thrift_application_base<TserverBase,
+ TImplClass>::d_default_num_thrift_threads));
+ buffersize = static_cast<unsigned int>
+ (gr::prefs::singleton()->get_long("thrift", "buffersize",
+ thrift_application_base<TserverBase,
+ TImplClass>::d_default_thrift_buffer_size));
+
+ d_serverTransport.reset(new thrift::transport::TServerSocket(port));
+
+ d_transportFactory.reset(new thrift_server_template::TBufferedTransportFactory(buffersize));
+
+ if(nthreads <= 1) {
+ // "Thrift: Single-threaded server"
+ //std::cout << "Thrift Single-threaded server" << std::endl;
+ thrift_application_base<TserverBase, TImplClass>::d_thriftserver.reset
+ (new thrift::server::TSimpleServer(d_processor, d_serverTransport,
+ d_transportFactory, d_protocolFactory));
+ }
+ else {
+ //std::cout << "Thrift Multi-threaded server : " << d_nthreads << std::endl;
+ boost::shared_ptr<thrift::concurrency::ThreadManager> threadManager
+ (thrift::concurrency::ThreadManager::newSimpleThreadManager(nthreads));
+
+ threadManager->threadFactory
+ (boost::shared_ptr<thrift::concurrency::PlatformThreadFactory>
+ (new thrift::concurrency::PlatformThreadFactory()));
+
+ threadManager->start();
+
+ thrift_application_base<TserverBase, TImplClass>::d_thriftserver.reset
+ (new thrift::server::TThreadPoolServer(d_processor, d_serverTransport,
+ d_transportFactory, d_protocolFactory,
+ threadManager));
+ }
+}
+
+template<typename TserverBase, typename TserverClass, typename TImplClass>
+thrift_server_template<TserverBase, TserverClass,TImplClass>::~thrift_server_template()
+{
+}
+
+template<typename TserverBase, typename TserverClass, typename TImplClass>
+TserverBase* thrift_server_template<TserverBase, TserverClass, TImplClass>::i_impl()
+{
+ //std::cerr << "thrift_server_template: i_impl" << std::endl;
+
+ return d_handler.get();
+}
+
+#endif /* THRIFT_SERVER_TEMPLATE_H */
diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt
index 6b4db0806f..cc51f97855 100644
--- a/gnuradio-runtime/lib/CMakeLists.txt
+++ b/gnuradio-runtime/lib/CMakeLists.txt
@@ -55,10 +55,15 @@ include_directories(${GNURADIO_RUNTIME_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/../include/
${VOLK_INCLUDE_DIRS}
- ${THRIFT_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
+if(ENABLE_CTRLPORT_THRIFT)
+ list(APPEND include_directories
+ ${THRIFT_INCLUDE_DIRS}
+ )
+endif(ENABLE_CTRLPORT_THRIFT)
+
########################################################################
# Include subdirs rather to populate to the sources lists.
########################################################################
@@ -209,20 +214,23 @@ add_dependencies(gnuradio-runtime
# STATIC LIB BUILD
#######################################################
if(ENABLE_STATIC_LIBS)
- # Remove controlport-specific source files from staticlibs build
+ # Remove controlport-specific source files from staticlibs build if
+ # ICE is the backend since it does not build statically.
if(ENABLE_GR_CTRLPORT)
- list(REMOVE_ITEM gnuradio_runtime_sources
- ${gnuradio_ctrlport_sources}
- )
-
- # Remove GR_CTRLPORT set this target's definitions.
- # Makes sure we don't try to use ControlPort stuff in source files
- GET_DIRECTORY_PROPERTY(STATIC_DEFS COMPILE_DEFINITIONS)
- list(REMOVE_ITEM STATIC_DEFS "GR_CTRLPORT")
- SET_PROPERTY(DIRECTORY PROPERTY COMPILE_DEFINITIONS "${STATIC_DEFS}")
-
- # readd it to the target since we removed it from the directory-wide list.
- SET_PROPERTY(TARGET gnuradio-runtime APPEND PROPERTY COMPILE_DEFINITIONS "GR_CTRLPORT")
+ if(ICE_FOUND)
+ list(REMOVE_ITEM gnuradio_runtime_sources
+ ${gnuradio_ctrlport_sources}
+ )
+
+ # Remove GR_CTRLPORT set this target's definitions.
+ # Makes sure we don't try to use ControlPort stuff in source files
+ GET_DIRECTORY_PROPERTY(STATIC_DEFS COMPILE_DEFINITIONS)
+ list(REMOVE_ITEM STATIC_DEFS "GR_CTRLPORT")
+ SET_PROPERTY(DIRECTORY PROPERTY COMPILE_DEFINITIONS "${STATIC_DEFS}")
+
+ # readd it to the target since we removed it from the directory-wide list.
+ SET_PROPERTY(TARGET gnuradio-runtime APPEND PROPERTY COMPILE_DEFINITIONS "GR_CTRLPORT")
+ endif(ICE_FOUND)
endif(ENABLE_GR_CTRLPORT)
add_library(gnuradio-runtime_static STATIC ${gnuradio_runtime_sources})
diff --git a/gnuradio-runtime/lib/block.cc b/gnuradio-runtime/lib/block.cc
index f26d6bb933..6edb73966d 100644
--- a/gnuradio-runtime/lib/block.cc
+++ b/gnuradio-runtime/lib/block.cc
@@ -842,42 +842,42 @@ namespace gr {
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >(
alias(), "input \% full", &block::pc_input_buffers_full,
- pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ pmt::make_f32vector(0,0), pmt::make_f32vector(0,1), pmt::make_f32vector(0,0),
"", "how full input buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >(
alias(), "avg input \% full", &block::pc_input_buffers_full_avg,
- pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ pmt::make_f32vector(0,0), pmt::make_f32vector(0,1), pmt::make_f32vector(0,0),
"", "Average of how full input buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >(
alias(), "var input \% full", &block::pc_input_buffers_full_var,
- pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ pmt::make_f32vector(0,0), pmt::make_f32vector(0,1), pmt::make_f32vector(0,0),
"", "Var. of how full input buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >(
alias(), "output \% full", &block::pc_output_buffers_full,
- pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ pmt::make_f32vector(0,0), pmt::make_f32vector(0,1), pmt::make_f32vector(0,0),
"", "how full output buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >(
alias(), "avg output \% full", &block::pc_output_buffers_full_avg,
- pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ pmt::make_f32vector(0,0), pmt::make_f32vector(0,1), pmt::make_f32vector(0,0),
"", "Average of how full output buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
d_rpc_vars.push_back(
rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >(
alias(), "var output \% full", &block::pc_output_buffers_full_var,
- pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0),
+ pmt::make_f32vector(0,0), pmt::make_f32vector(0,1), pmt::make_f32vector(0,0),
"", "Var. of how full output buffers are", RPC_PRIVLVL_MIN,
DISPTIME | DISPOPTSTRIP)));
#endif /* defined(GR_CTRLPORT) && defined(GR_PERFORMANCE_COUNTERS) */
diff --git a/gnuradio-runtime/lib/controlport/CMakeLists.txt b/gnuradio-runtime/lib/controlport/CMakeLists.txt
index 262c5adb8b..f0d2618c01 100644
--- a/gnuradio-runtime/lib/controlport/CMakeLists.txt
+++ b/gnuradio-runtime/lib/controlport/CMakeLists.txt
@@ -19,8 +19,13 @@
if(ENABLE_GR_CTRLPORT)
+# Keep track of the number of backends ControlPort supports
+SET(CTRLPORT_BACKENDS 0)
+
# Add definition so we can compile in ControlPort to the blocks.
-ADD_DEFINITIONS(-DGR_CTRLPORT)
+add_definitions(-DGR_CTRLPORT)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
list(APPEND gnuradio_ctrlport_sources
${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager.cc
@@ -29,14 +34,71 @@ list(APPEND gnuradio_ctrlport_sources
${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_selector.cc
)
+
+OPTION(ENABLE_CTRLPORT_THRIFT "Enable ControlPort Thrift support" ON)
+
+if(ENABLE_CTRLPORT_THRIFT)
+
+# Look if Thrift is installed and use it as a ControlPort backend.
+FIND_PACKAGE(Thrift)
+
+if(THRIFT_FOUND)
+
+MATH(EXPR CTRLPORT_BACKENDS "${CTRLPORT_BACKENDS} + 1")
+
+# Indicate thrift as an installed backend in the cmake summary.
+message(STATUS "Found and enabling Thrift backend to ControlPort")
+GR_APPEND_SUBCOMPONENT("thrift")
+
+# Run Thrrift To compile C++ and Python files
+message(STATUS "Running thrift to build C++ bindings")
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/)
+EXECUTE_PROCESS(
+ COMMAND ${THRIFT_BIN} --gen cpp -out ${CMAKE_CURRENT_BINARY_DIR}/thrift/ ${CMAKE_CURRENT_SOURCE_DIR}/thrift/gnuradio.thrift
+ OUTPUT_VARIABLE THRIFT_CPP_OUTPUT
+ ERROR_VARIABLE THRIFT_CPP_ERROR
+ )
+
+list(APPEND gnuradio_ctrlport_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/thrift/rpcserver_thrift.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/thrift/rpcpmtconverters_thrift.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/thrift/rpcserver_booter_thrift.cc
+ ${CMAKE_CURRENT_SOURCE_DIR}/thrift/thrift_application_base.cc
+)
+
+# add files built by compiling gnuradio.thrift
+list(APPEND gnuradio_ctrlport_sources
+ ${CMAKE_CURRENT_BINARY_DIR}/thrift/gnuradio_types.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/thrift/gnuradio_constants.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/thrift/ControlPort.cpp
+)
+
+# Add required libraries here
+list(APPEND gnuradio_runtime_libs
+ ${THRIFT_LIBRARIES}
+)
+
+# Add install rule to move example Thrift configuration file into
+# $prefix/etc/gnuradio
+install(
+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/thrift/thrift.conf.example
+ DESTINATION ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}
+ COMPONENT "runtime_runtime"
+)
+
+endif(THRIFT_FOUND)
+endif(ENABLE_CTRLPORT_THRIFT)
+
########################################################################
# Add controlport stuff to gnuradio-runtime
########################################################################
include_directories(${CMAKE_CURRENT_BINARY_DIR})
-# Add any required libraries here
-#list(APPEND gnuradio_runtime_libs
-#)
+# Save the number of backends for testing against later
+set(
+ CTRLPORT_BACKENDS ${CTRLPORT_BACKENDS}
+ CACHE INTERNAL "Number of ControlPort backends available"
+)
endif(ENABLE_GR_CTRLPORT)
diff --git a/gnuradio-runtime/lib/controlport/rpcmanager.cc b/gnuradio-runtime/lib/controlport/rpcmanager.cc
index 0c7bc135be..a67febe386 100644
--- a/gnuradio-runtime/lib/controlport/rpcmanager.cc
+++ b/gnuradio-runtime/lib/controlport/rpcmanager.cc
@@ -26,16 +26,12 @@
bool rpcmanager::booter_registered(false);
bool rpcmanager::aggregator_registered(false);
-rpcserver_booter_base* rpcmanager::boot(0);
+std::auto_ptr<rpcserver_booter_base> rpcmanager::boot(0);
std::auto_ptr<rpcserver_booter_aggregator> rpcmanager::aggregator(0);
rpcmanager::rpcmanager() {;}
-rpcmanager::~rpcmanager()
-{
- if(boot)
- delete boot;
-}
+rpcmanager::~rpcmanager() {;}
rpcserver_booter_base*
rpcmanager::get()
@@ -44,10 +40,10 @@ rpcmanager::get()
return aggregator.get();
}
else if(booter_registered) {
- return boot;
+ return boot.get();
}
assert(booter_registered || aggregator_registered);
- return boot;
+ return boot.get();
}
void
@@ -63,7 +59,7 @@ rpcmanager::register_booter(rpcserver_booter_base* booter)
aggregator->agg()->registerServer(bootreg);
}
else if(!booter_registered) {
- boot = booter;
+ boot.reset(booter);
booter_registered = true;
}
else {
diff --git a/gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc b/gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc
index 201dfb3929..a1983b4ac5 100644
--- a/gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc
+++ b/gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc
@@ -23,7 +23,8 @@
#include <gnuradio/rpcserver_booter_aggregator.h>
rpcserver_booter_aggregator::rpcserver_booter_aggregator() :
- d_type(std::string("aggregator")), server(new rpcserver_aggregator())
+ d_type(std::string("aggregator")),
+ server(new rpcserver_aggregator())
{;}
rpcserver_booter_aggregator::~rpcserver_booter_aggregator()
diff --git a/gnuradio-runtime/lib/controlport/rpcserver_selector.cc b/gnuradio-runtime/lib/controlport/rpcserver_selector.cc
index 692f151958..8f3b4557c2 100644
--- a/gnuradio-runtime/lib/controlport/rpcserver_selector.cc
+++ b/gnuradio-runtime/lib/controlport/rpcserver_selector.cc
@@ -26,14 +26,23 @@
bool rpcmanager::make_aggregator(false);
-#ifdef RPCSERVER_ICE
+#ifdef GR_RPCSERVER_ENABLED
+rpcmanager manager_instance;
+#endif
+
+#ifdef GR_RPCSERVER_ICE
#error TODO ICE
#endif
-#ifdef RPCSERVER_ERLANG
+#ifdef GR_RPCSERVER_THRIFT
+#include <gnuradio/rpcserver_booter_thrift.h>
+rpcmanager::rpcserver_booter_register_helper<rpcserver_booter_thrift> boot_thrift;
+#endif
+
+#ifdef GR_RPCSERVER_ERLANG
#error TODO ERLANG
#endif
-#ifdef RPCSERVER_XMLRPC
+#ifdef GR_RPCSERVER_XMLRPC
#error TODO XMLRPC
#endif
diff --git a/gnuradio-runtime/lib/controlport/thrift/README b/gnuradio-runtime/lib/controlport/thrift/README
new file mode 100644
index 0000000000..5448e512f7
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/README
@@ -0,0 +1,41 @@
+For info on ControlPort and Thrift, see the wiki page:
+
+http://gnuradio.org/redmine/projects/gnuradio/wiki/ControlPort
+
+This readme is to address the patch file in the repo for Thrift. We
+believe that there is a bug in Thrift itself that occasionally causes
+a segfault when shutting down the server. If you run into a problem
+when shutting down an application running ControlPort, this might be
+the cause. If so, we have included a patch with the source code in
+this directory that should be applied to Thrift before rebuilding the
+Thrift library:
+
+thrift-codebase-shutdown-patch.diff
+
+Note that we are working off Thrift version 0.9.2, so this patch may
+not be relevant or even cleanly apply in later versions of Thrift.
+
+We are also still trying to track down another shutdown problem with
+Thrift that again appears to be related to their code. If a segfault
+persists after the above patch is applied to Thrift, do a backtrace in
+GDB to see what the error looks like. If it is different than the
+following backtrace, definitely report it to the Discuss GNU Radio
+Mailing List as a known bug. If you see the same backtrace as here,
+this is a known bug that occurs very irregularly, but help in tracing
+down the cause is appreciated.
+
+#0 0x00007f07b5b478c2 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
+(gdb) bt
+#0 0x00007f07b5b478c2 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
+#1 0x00007f07b5b4856d in ?? () from /lib/x86_64-linux-gnu/libc.so.6
+#2 0x00007f07afc924c5 in std::locale::_Impl::~_Impl() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
+#3 0x00007f07afc925fd in std::locale::~locale() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
+#4 0x00007f07b5b05259 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
+#5 0x00007f07b5b052a5 in exit () from /lib/x86_64-linux-gnu/libc.so.6
+#6 0x000000000042fb83 in Py_Exit ()
+#7 0x000000000042fcb9 in ?? ()
+#8 0x000000000042ec32 in PyErr_PrintEx ()
+#9 0x0000000000469f2f in PyRun_SimpleFileExFlags ()
+#10 0x000000000046ab81 in Py_Main ()
+#11 0x00007f07b5aeaec5 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
+#12 0x000000000057497e in _start ()
diff --git a/gnuradio-runtime/lib/controlport/thrift/gnuradio.thrift b/gnuradio-runtime/lib/controlport/thrift/gnuradio.thrift
new file mode 100644
index 0000000000..ae7f839a2f
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/gnuradio.thrift
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2014,2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+namespace cpp GNURadio
+namespace py GNURadio
+
+struct complex {
+ 1: double re;
+ 2: double im;
+}
+
+typedef list<bool> VectorB
+typedef binary VectorC
+typedef list<i16> VectorT
+typedef list<i32> VectorI
+typedef list<i64> VectorL
+typedef list<double> VectorF
+typedef list<double> VectorD
+typedef list<string> VectorS
+typedef list<complex> VectorZ
+
+enum BaseTypes { BOOL, BYTE, SHORT, INT, LONG, DOUBLE, STRING, COMPLEX,
+ F32VECTOR, F64VECTOR, S64VECTOR, S32VECTOR, S16VECTOR,
+ S8VECTOR, C32VECTOR }
+
+union KnobBase {
+ 1: bool a_bool;
+ 2: byte a_byte;
+ 3: i16 a_short;
+ 4: i32 a_int;
+ 5: i64 a_long;
+ 6: double a_double;
+ 7: string a_string;
+ 8: complex a_complex;
+ 9: VectorF a_f32vector;
+ 10: VectorD a_f64vector;
+ 11: VectorL a_s64vector;
+ 12: VectorI a_s32vector;
+ 13: VectorT a_s16vector;
+ 14: VectorC a_s8vector;
+ 15: VectorZ a_c32vector;
+}
+
+struct Knob {
+ 1: BaseTypes type;
+ 2: KnobBase value;
+}
+
+enum KnobType { KNOBBOOL, KNOBCHAR, KNOBINT, KNOBDOUBLE, KNOBSTRING,
+ KNOBLONG, KNOBVECBOOL, KNOBVECCHAR, KNOBVECINT,
+ KNOBVECDOUBLE, KNOBVECSTRING, KNOBVECLONG, KNOBSHORT}
+
+const i32 DISPNULL = 0x0000
+const i32 DISPTIME = 0x0001
+const i32 DISPXY = 0x0002
+const i32 DISPPSD = 0x0004
+const i32 DISPSPEC = 0x0008
+const i32 DISPRAST = 0x0010
+const i32 DISPOPTCPLX = 0x0100
+const i32 DISPOPTLOG = 0x0200
+const i32 DISPOPTSTEM = 0x0400
+const i32 DISPOPTSTRIP = 0x0800
+const i32 DISPOPTSCATTER = 0x1000
+
+struct KnobProp {
+ 1: KnobType type,
+ 2: string units,
+ 3: string description,
+ 4: i32 display,
+ 5: Knob min,
+ 6: Knob max,
+ 7: Knob defaultvalue
+}
+
+typedef list<string> KnobIDList
+typedef map<string, Knob> KnobMap
+typedef map<string, KnobProp> KnobPropMap
+typedef map<string, string> WaveformArgMap
+
+service StreamReceiver {
+ void push(1:VectorC data);
+}
+
+service ControlPort {
+ void setKnobs(1:KnobMap knobs);
+ KnobMap getKnobs(1:KnobIDList knobs);
+ KnobMap getRe(1:KnobIDList knobs);
+ KnobPropMap properties(1:KnobIDList knobs);
+ void shutdown();
+}
diff --git a/gnuradio-runtime/lib/controlport/thrift/rpcpmtconverters_thrift.cc b/gnuradio-runtime/lib/controlport/thrift/rpcpmtconverters_thrift.cc
new file mode 100644
index 0000000000..cc8804f79d
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/rpcpmtconverters_thrift.cc
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2014,2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <boost/assign/ptr_map_inserter.hpp>
+#include <gnuradio/rpcpmtconverters_thrift.h>
+#include <gnuradio/gr_complex.h>
+#include "thrift/gnuradio_types.h"
+#include <iostream>
+
+GNURadio::Knob
+rpcpmtconverter::from_pmt(const pmt::pmt_t& knob)
+{
+ if(pmt::is_real(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::DOUBLE;
+ result.value.__set_a_double(pmt::to_double(knob));
+ return result;
+ }
+ else if(pmt::is_symbol(knob)) {
+ std::string value = pmt::symbol_to_string(knob);
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::STRING;
+ result.value.__set_a_string(value);
+ return result;
+ }
+ else if(pmt::is_integer(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::LONG;
+ result.value.__set_a_long(pmt::to_long(knob));
+ return result;
+ }
+ else if(pmt::is_bool(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::BOOL;
+ result.value.__set_a_bool(pmt::to_bool(knob));
+ return result;
+ }
+ else if(pmt::is_uint64(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::LONG;
+ result.value.__set_a_long(pmt::to_uint64(knob));
+ return result;
+ }
+ else if(pmt::is_complex(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::COMPLEX;
+ std::complex<double> tmp = pmt::to_complex(knob);
+ GNURadio::complex cpx;
+ cpx.re = tmp.real();
+ cpx.im = tmp.imag();
+ result.value.__set_a_complex(cpx);
+ return result;
+ }
+ else if(pmt::is_f32vector(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::F32VECTOR;
+ size_t size(pmt::length(knob));
+ const float* start((const float*)pmt::f32vector_elements(knob,size));
+ result.value.__set_a_f32vector(std::vector<double>(start,start+size));
+ return result;
+ }
+ else if(pmt::is_f64vector(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::F64VECTOR;
+ size_t size(pmt::length(knob));
+ const double* start((const double*)pmt::f64vector_elements(knob,size));
+ result.value.__set_a_f64vector(std::vector<double>(start,start+size));
+ return result;
+ }
+ else if(pmt::is_s64vector(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::S64VECTOR;
+ size_t size(pmt::length(knob));
+ const int64_t* start((const int64_t*)pmt::s64vector_elements(knob,size));
+ result.value.__set_a_s64vector(std::vector<int64_t>(start,start+size));
+ return result;
+ }
+ else if(pmt::is_s32vector(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::S32VECTOR;
+ size_t size(pmt::length(knob));
+ const int32_t* start((const int32_t*)pmt::s32vector_elements(knob,size));
+ result.value.__set_a_s32vector(std::vector<int32_t>(start,start+size));
+ return result;
+ }
+ else if(pmt::is_s16vector(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::S16VECTOR;
+ size_t size(pmt::length(knob));
+ const int16_t* start((const int16_t*)pmt::s16vector_elements(knob,size));
+ result.value.__set_a_s16vector(std::vector<int16_t>(start,start+size));
+ return result;
+ }
+ else if(pmt::is_s8vector(knob)) {
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::S8VECTOR;
+ size_t size(pmt::length(knob));
+ const int8_t* start((const int8_t*)pmt::s8vector_elements(knob,size));
+ result.value.__set_a_s8vector(std::basic_string<char>(start,start+size));
+ return result;
+ }
+ else if(pmt::is_c32vector(knob)) {
+ std::vector< GNURadio::complex > z;
+
+ GNURadio::Knob result;
+ result.type = GNURadio::BaseTypes::C32VECTOR;
+ size_t size(pmt::length(knob));
+ const gr_complex* start((const gr_complex*)pmt::c32vector_elements(knob,size));
+ for(size_t s = 0; s < size; s++) {
+ GNURadio::complex z0;
+ gr_complex z1 = gr_complex(*(start+s));
+ z0.__set_re(z1.real());
+ z0.__set_im(z1.imag());
+ z.push_back(z0);
+ }
+ result.value.__set_a_c32vector(z);
+ return result;
+ }
+ else {
+ std::cerr << "Error: Don't know how to handle Knob Type (from): " << knob << std::endl;
+ assert(0);
+ }
+ return GNURadio::Knob();
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_byte_f::operator()(const GNURadio::Knob& knob)
+{
+ return pmt::mp(knob.value.a_byte);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_short_f::operator()(const GNURadio::Knob& knob)
+{
+ return pmt::mp(knob.value.a_short);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_int_f::operator()(const GNURadio::Knob& knob)
+{
+ return pmt::mp(knob.value.a_int);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_long_f::operator()(const GNURadio::Knob& knob)
+{
+ return pmt::from_long(knob.value.a_long);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_double_f::operator()(const GNURadio::Knob& knob)
+{
+ return pmt::mp(knob.value.a_double);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_string_f::operator()(const GNURadio::Knob& knob)
+{
+ return pmt::string_to_symbol(knob.value.a_string);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_bool_f::operator()(const GNURadio::Knob& knob)
+{
+ if(knob.value.a_bool)
+ return pmt::PMT_T;
+ else
+ return pmt::PMT_F;
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_complex_f::operator()(const GNURadio::Knob& knob)
+{
+ gr_complexd cpx(knob.value.a_complex.re, knob.value.a_complex.im);
+ return pmt::from_complex(cpx);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_f32vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::vector<double> v_double = knob.value.a_f32vector;
+ std::vector<float> v(v_double.begin(), v_double.end());
+ return pmt::init_f32vector(v.size(), v);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_f64vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::vector<double> v = knob.value.a_f64vector;
+ return pmt::init_f64vector(v.size(), v);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_s64vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::vector<int64_t> v = knob.value.a_s64vector;
+ return pmt::init_s64vector(v.size(), v);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_s32vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::vector<int32_t> v = knob.value.a_s32vector;
+ return pmt::init_s32vector(v.size(), v);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_s16vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::vector<int16_t> v = knob.value.a_s16vector;
+ return pmt::init_s16vector(v.size(), v);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_s8vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::basic_string<char> v = knob.value.a_s8vector;
+ return pmt::init_s8vector(v.size(), reinterpret_cast<const int8_t*>(v.data()));
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_c32vect_f::operator()(const GNURadio::Knob& knob)
+{
+ std::vector<GNURadio::complex> v0 = knob.value.a_c32vector;
+ std::vector<GNURadio::complex>::iterator vitr;
+ std::vector<gr_complex> v;
+ for(vitr = v0.begin(); vitr != v0.end(); vitr++) {
+ v.push_back(gr_complex(vitr->re, vitr->im));
+ }
+ return pmt::init_c32vector(v.size(), v);
+}
+
+rpcpmtconverter::To_PMT rpcpmtconverter::To_PMT::instance;
+
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_bool_f> reg_bool(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::BOOL);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_byte_f> reg_byte(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::BYTE);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_short_f> reg_short(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::SHORT);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_int_f> reg_int(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::INT);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_long_f> reg_long(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::LONG);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_double_f> reg_double(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::DOUBLE);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_string_f> reg_string(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::STRING);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_complex_f> reg_complex(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::COMPLEX);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_f32vect_f> reg_f32v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::F32VECTOR);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_f64vect_f> reg_f64v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::F64VECTOR);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_s64vect_f> reg_s64v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::S64VECTOR);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_s32vect_f> reg_s32v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::S32VECTOR);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_s16vect_f> reg_s16v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::S16VECTOR);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_s8vect_f> reg_s8v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::S8VECTOR);
+rpcpmtconverter::to_pmt_reg<rpcpmtconverter::to_pmt_c32vect_f> reg_c32v(rpcpmtconverter::To_PMT::instance,
+ GNURadio::BaseTypes::C32VECTOR);
+
+template<typename TO_PMT_F>
+rpcpmtconverter::to_pmt_reg<TO_PMT_F>::to_pmt_reg(To_PMT& instance,
+ const GNURadio::BaseTypes::type type)
+{
+ boost::assign::ptr_map_insert<TO_PMT_F>(instance.to_pmt_map)(type);
+}
+
+pmt::pmt_t
+rpcpmtconverter::to_pmt_f::operator()(const GNURadio::Knob& knob)
+{
+ std::cerr << "Error: Don't know how to handle Knob Type: " << knob.type << std::endl;
+ assert(0);
+ return pmt::pmt_t();
+}
+
+pmt::pmt_t
+rpcpmtconverter::To_PMT::operator()(const GNURadio::Knob& knob)
+{
+ return to_pmt_map[knob.type](knob);
+}
diff --git a/gnuradio-runtime/lib/controlport/thrift/rpcserver_booter_thrift.cc b/gnuradio-runtime/lib/controlport/thrift/rpcserver_booter_thrift.cc
new file mode 100644
index 0000000000..1d6cafe0c0
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/rpcserver_booter_thrift.cc
@@ -0,0 +1,133 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/rpcserver_thrift.h>
+#include <gnuradio/rpcserver_booter_thrift.h>
+
+#include <boost/asio/ip/host_name.hpp>
+
+namespace {
+ static const char* const CONTROL_PORT_CLASS("thrift");
+ static const unsigned int ETHERNET_HEADER_SIZE(14);
+ static const unsigned int IP_HEADER_SIZE(20);
+ static const unsigned int TCP_HEADER_SIZE(32);
+ static const unsigned int ETHERNET_TYPICAL_MTU(1500);
+ static const unsigned int ALRIGHT_DEFAULT_BUFFER_SIZE(
+ ETHERNET_TYPICAL_MTU - ETHERNET_HEADER_SIZE - IP_HEADER_SIZE - TCP_HEADER_SIZE);
+};
+
+/*!
+ * \brief A booter implementation for a Thrift application class.
+ */
+
+rpcserver_booter_thrift::rpcserver_booter_thrift() :
+ thrift_server_template<rpcserver_base,
+ rpcserver_thrift,
+ rpcserver_booter_thrift>(this),
+ d_type(std::string(CONTROL_PORT_CLASS))
+{;}
+
+rpcserver_booter_thrift::~rpcserver_booter_thrift()
+{;}
+
+rpcserver_base*
+rpcserver_booter_thrift::i()
+{
+ return thrift_server_template<rpcserver_base, rpcserver_thrift,
+ rpcserver_booter_thrift>::i();
+}
+
+/*!
+ * \brief Returns the endpoint string for the application
+ */
+
+const std::vector<std::string>
+rpcserver_booter_thrift::endpoints()
+{
+ return thrift_server_template<rpcserver_base, rpcserver_thrift,
+ rpcserver_booter_thrift>::endpoints();
+}
+
+// Specialized thrift_application_base attributes and functions
+// for this rpcserver_booter instance.
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+const unsigned int thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::d_default_max_init_attempts(100U);
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+const unsigned int thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::d_default_thrift_port(0U);
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+const unsigned int thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::d_default_num_thrift_threads(10U);
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+const unsigned int thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::d_default_thrift_buffer_size(
+ ALRIGHT_DEFAULT_BUFFER_SIZE);
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+boost::scoped_ptr<thrift_application_base_impl>
+ thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::p_impl(
+ new thrift_application_base_impl());
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::~thrift_application_base()
+{
+ if(d_thirft_is_running) {
+ d_thriftserver->stop();
+ d_thirft_is_running = false;
+ }
+}
+
+template<class rpcserver_base, class rpcserver_booter_thrift>
+void thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::start_thrift()
+{
+ d_thriftserver->serve();
+}
+
+template<class rpcserver_base, typename rpcserver_booter_thrift>
+bool thrift_application_base<rpcserver_base, rpcserver_booter_thrift>::application_started()
+{
+ if (d_thirft_is_running) return true;
+
+ bool result(false);
+ // Define the endpoint.
+ apache::thrift::transport::TServerTransport *thetransport =
+ d_thriftserver->getServerTransport().get();
+
+ // Determine the specified endpoint port number, or the port number selected by bind() if
+ int used_port = ((apache::thrift::transport::TServerSocket*)thetransport)->getPort();
+
+ if (used_port > 0) {
+ // Determine the hostname of this host
+ const std::string boost_hostname(boost::asio::ip::host_name());
+
+ std::string endpoint = boost::str(boost::format("-h %1% -p %2%") % boost_hostname % used_port);
+
+ set_endpoint(endpoint);
+
+ GR_LOG_INFO(d_logger, "Apache Thrift: " + endpoint);
+ d_thirft_is_running = true;
+ result = true;
+ }
+
+ return result;
+}
diff --git a/gnuradio-runtime/lib/controlport/thrift/rpcserver_thrift.cc b/gnuradio-runtime/lib/controlport/thrift/rpcserver_thrift.cc
new file mode 100644
index 0000000000..3e6eabc854
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/rpcserver_thrift.cc
@@ -0,0 +1,202 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014,2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/rpcserver_thrift.h>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <pmt/pmt.h>
+#include <thrift/protocol/TBinaryProtocol.h>
+#include <thrift/transport/TSocket.h>
+#include <thrift/transport/TTransportUtils.h>
+#include <boost/xpressive/xpressive.hpp>
+#include "thrift/ControlPort.h"
+
+#define DEBUG 0
+
+using namespace rpcpmtconverter;
+
+rpcserver_thrift::rpcserver_thrift()
+{
+ //std::cerr << "rpcserver_thrift::ctor" << std::endl;
+}
+
+rpcserver_thrift::~rpcserver_thrift()
+{
+ //std::cerr << "rpcserver_thrift::dtor" << std::endl;
+}
+
+void
+rpcserver_thrift::registerConfigureCallback(const std::string &id,
+ const configureCallback_t callback)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ {
+ ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(id));
+ if(iter != d_setcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_thrift:: rpcserver_thrift ERROR registering set, already registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+ }
+
+ if(DEBUG) {
+ std::cerr << "rpcserver_thrift registering set: " << id << std::endl;
+ }
+ d_setcallbackmap.insert(ConfigureCallbackMap_t::value_type(id, callback));
+}
+
+void
+rpcserver_thrift::unregisterConfigureCallback(const std::string &id)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ ConfigureCallbackMap_t::iterator iter(d_setcallbackmap.find(id));
+ if(iter == d_setcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_thrift:: rpcserver_thrift ERROR unregistering set, not registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ if(DEBUG)
+ std::cerr << "rpcserver_thrift unregistering set: " << id << std::endl;
+
+ d_setcallbackmap.erase(iter);
+}
+
+void
+rpcserver_thrift::registerQueryCallback(const std::string &id,
+ const queryCallback_t callback)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ {
+ QueryCallbackMap_t::const_iterator iter(d_getcallbackmap.find(id));
+ if(iter != d_getcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_thrift:: rpcserver_thrift ERROR registering get, already registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+ }
+
+ if(DEBUG) {
+ std::cerr << "rpcserver_thrift registering get: " << id << std::endl;
+ }
+ d_getcallbackmap.insert(QueryCallbackMap_t::value_type(id, callback));
+}
+
+void
+rpcserver_thrift::unregisterQueryCallback(const std::string &id)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ QueryCallbackMap_t::iterator iter(d_getcallbackmap.find(id));
+ if(iter == d_getcallbackmap.end()) {
+ std::stringstream s;
+ s << "rpcserver_thrift:: rpcserver_thrift ERROR unregistering get, registered: "
+ << id << std::endl;
+ throw std::runtime_error(s.str().c_str());
+ }
+
+ if(DEBUG) {
+ std::cerr << "rpcserver_thrift unregistering get: " << id << std::endl;
+ }
+
+ d_getcallbackmap.erase(iter);
+}
+
+void
+rpcserver_thrift::setKnobs(const GNURadio::KnobMap& knobs)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ std::for_each(knobs.begin(), knobs.end(),
+ set_f<GNURadio::KnobMap::value_type,ConfigureCallbackMap_t>
+ (d_setcallbackmap, cur_priv));
+}
+
+
+void
+rpcserver_thrift::getKnobs(GNURadio::KnobMap& _return,
+ const GNURadio::KnobIDList& knobs)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ if(knobs.size() == 0) {
+ std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(),
+ get_all_f<QueryCallbackMap_t::value_type, QueryCallbackMap_t, GNURadio::KnobMap>
+ (d_getcallbackmap, cur_priv, _return));
+ }
+ else {
+ std::for_each(knobs.begin(), knobs.end(),
+ get_f<GNURadio::KnobIDList::value_type, QueryCallbackMap_t>
+ (d_getcallbackmap, cur_priv, _return));
+ }
+}
+
+void
+rpcserver_thrift::getRe(GNURadio::KnobMap& _return, const GNURadio::KnobIDList& knobs)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ if(knobs.size() == 0) {
+ std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(),
+ get_all_f<QueryCallbackMap_t::value_type, QueryCallbackMap_t, GNURadio::KnobMap>
+ (d_getcallbackmap, cur_priv, _return));
+ }
+ else {
+ QueryCallbackMap_t::iterator it;
+ for(it = d_getcallbackmap.begin(); it != d_getcallbackmap.end(); it++){
+ for(size_t j=0; j<knobs.size(); j++) {
+ const boost::xpressive::sregex re(boost::xpressive::sregex::compile(knobs[j]));
+ if(boost::xpressive::regex_match(it->first, re)) {
+ get_f<GNURadio::KnobIDList::value_type, QueryCallbackMap_t>
+ (d_getcallbackmap, cur_priv, _return)(it->first);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void
+rpcserver_thrift::properties(GNURadio::KnobPropMap& _return,
+ const GNURadio::KnobIDList& knobs)
+{
+ boost::mutex::scoped_lock lock(d_callback_map_lock);
+ if(knobs.size() == 0) {
+ std::for_each(d_getcallbackmap.begin(), d_getcallbackmap.end(),
+ properties_all_f<QueryCallbackMap_t::value_type,
+ QueryCallbackMap_t, GNURadio::KnobPropMap>(d_getcallbackmap,
+ cur_priv, _return));
+ }
+ else {
+ std::for_each(knobs.begin(), knobs.end(),
+ properties_f<GNURadio::KnobIDList::value_type,
+ QueryCallbackMap_t, GNURadio::KnobPropMap>(d_getcallbackmap,
+ cur_priv, _return));
+ }
+}
+
+void
+rpcserver_thrift::shutdown() {
+ if (DEBUG) {
+ std::cerr << "Shutting down..." << std::endl;
+ }
+}
diff --git a/gnuradio-runtime/lib/controlport/thrift/thrift-codebase-shutdown-patch.diff b/gnuradio-runtime/lib/controlport/thrift/thrift-codebase-shutdown-patch.diff
new file mode 100644
index 0000000000..eaf54d5c70
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/thrift-codebase-shutdown-patch.diff
@@ -0,0 +1,98 @@
+diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
+index 255d237..9954a8a 100644
+--- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
++++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp
+@@ -409,6 +409,8 @@ void ThreadManager::Impl::removeWorker(size_t value) {
+
+ workerMaxCount_ -= value;
+
++ shutdown_mutex_.unlock();
++
+ if (idleCount_ < value) {
+ for (size_t ix = 0; ix < idleCount_; ix++) {
+ monitor_.notify();
+diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.h b/lib/cpp/src/thrift/concurrency/ThreadManager.h
+index 7bb71d1..e97fd25 100644
+--- a/lib/cpp/src/thrift/concurrency/ThreadManager.h
++++ b/lib/cpp/src/thrift/concurrency/ThreadManager.h
+@@ -24,6 +24,7 @@
+ #include <thrift/cxxfunctional.h>
+ #include <sys/types.h>
+ #include <thrift/concurrency/Thread.h>
++#include <thrift/concurrency/Mutex.h>
+
+ namespace apache {
+ namespace thrift {
+@@ -59,6 +60,7 @@ protected:
+ ThreadManager() {}
+
+ public:
++ Mutex shutdown_mutex_;
+ typedef apache::thrift::stdcxx::function<void(boost::shared_ptr<Runnable>)> ExpireCallback;
+
+ virtual ~ThreadManager() {}
+diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
+index 0530d8d..d6b73dc 100644
+--- a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
++++ b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp
+@@ -194,19 +194,28 @@ void TThreadPoolServer::serve() {
+ }
+ }
+
+- // If stopped manually, join the existing threads
+- if (stop_) {
+- try {
+- serverTransport_->close();
+- threadManager_->join();
+- } catch (TException& tx) {
+- string errStr = string("TThreadPoolServer: Exception shutting down: ") + tx.what();
+- GlobalOutput(errStr.c_str());
++ {
++ Guard g(threadManager_->shutdown_mutex_);
++ // If stopped manually, join the existing threads
++ if (stop_) {
++ try {
++ serverTransport_->close();
++ threadManager_->join();
++ } catch (TException& tx) {
++ string errStr = string("TThreadPoolServer: Exception shutting down: ") + tx.what();
++ GlobalOutput(errStr.c_str());
++ }
++ stop_ = false;
+ }
+- stop_ = false;
+ }
+ }
+
++void TThreadPoolServer::stop() {
++ threadManager_->shutdown_mutex_.lock();
++ stop_ = true;
++ serverTransport_->interrupt();
++}
++
+ int64_t TThreadPoolServer::getTimeout() const {
+ return timeout_;
+ }
+diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.h b/lib/cpp/src/thrift/server/TThreadPoolServer.h
+index ad7e7ef..9b89846 100644
+--- a/lib/cpp/src/thrift/server/TThreadPoolServer.h
++++ b/lib/cpp/src/thrift/server/TThreadPoolServer.h
+@@ -24,6 +24,7 @@
+ #include <thrift/server/TServer.h>
+ #include <thrift/transport/TServerTransport.h>
+
++
+ #include <boost/shared_ptr.hpp>
+
+ namespace apache {
+@@ -113,10 +114,7 @@ public:
+
+ virtual void setTimeout(int64_t value);
+
+- virtual void stop() {
+- stop_ = true;
+- serverTransport_->interrupt();
+- }
++ virtual void stop();
+
+ virtual int64_t getTaskExpiration() const;
diff --git a/gnuradio-runtime/lib/controlport/thrift/thrift.conf.example b/gnuradio-runtime/lib/controlport/thrift/thrift.conf.example
new file mode 100644
index 0000000000..71cc506249
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/thrift.conf.example
@@ -0,0 +1,4 @@
+[thrift]
+port = 9090
+nthreads = 2
+buffersize = 1434
diff --git a/gnuradio-runtime/lib/controlport/thrift/thrift_application_base.cc b/gnuradio-runtime/lib/controlport/thrift/thrift_application_base.cc
new file mode 100644
index 0000000000..282ed9fc63
--- /dev/null
+++ b/gnuradio-runtime/lib/controlport/thrift/thrift_application_base.cc
@@ -0,0 +1,23 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gnuradio/thrift_application_base.h>
diff --git a/gnuradio-runtime/lib/prefs.cc b/gnuradio-runtime/lib/prefs.cc
index b7fcaada9d..b303ffdaf9 100644
--- a/gnuradio-runtime/lib/prefs.cc
+++ b/gnuradio-runtime/lib/prefs.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006,2013 Free Software Foundation, Inc.
+ * Copyright 2006,2013,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -46,7 +46,10 @@ namespace gr {
prefs::prefs()
{
- _read_files();
+ std::string config = _read_files(_sys_prefs_filenames());
+
+ // Convert the string into a map
+ _convert_to_map(config);
}
prefs::~prefs()
@@ -83,13 +86,12 @@ namespace gr {
return fnames;
}
- void
- prefs::_read_files()
+ std::string
+ prefs::_read_files(const std::vector<std::string> &filenames)
{
std::string config;
- std::vector<std::string> filenames = _sys_prefs_filenames();
- std::vector<std::string>::iterator sitr;
+ std::vector<std::string>::const_iterator sitr;
char tmp[1024];
for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) {
fs::ifstream fin(*sitr);
@@ -142,8 +144,7 @@ namespace gr {
fin.close();
}
- // Convert the string into a map
- _convert_to_map(config);
+ return config;
}
void
@@ -188,6 +189,17 @@ namespace gr {
}
}
+ void
+ prefs::add_config_file(const std::string &configfile)
+ {
+ std::vector<std::string> filenames;
+ filenames.push_back(configfile);
+
+ std::string config = _read_files(filenames);
+ _convert_to_map(config);
+ }
+
+
std::string
prefs::to_string()
{
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt
index 1d5a292429..f40f253a72 100644
--- a/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt
@@ -27,10 +27,53 @@ install(
COMPONENT "runtime_python"
)
+
GR_PYTHON_INSTALL(
FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py
${CMAKE_CURRENT_SOURCE_DIR}/GrDataPlotter.py
${CMAKE_CURRENT_SOURCE_DIR}/monitor.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/GNURadioControlPortClient.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/RPCConnection.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/
+ COMPONENT "runtime_python"
+)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr-perf-monitorx
+ ${CMAKE_CURRENT_SOURCE_DIR}/gr-ctrlport-monitor
+ DESTINATION ${GR_RUNTIME_DIR}
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+ COMPONENT "runtime_python"
+)
+
+if(THRIFT_FOUND)
+
+EXECUTE_PROCESS(
+ COMMAND ${THRIFT_BIN} --gen py -out ${CMAKE_CURRENT_BINARY_DIR}/ ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/controlport/thrift/gnuradio.thrift
+ OUTPUT_VARIABLE THRIFT_PY_OUTPUT
+ ERROR_VARIABLE THRIFT_PY_ERROR
+ )
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/RPCConnectionThrift.py
DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/
COMPONENT "runtime_python"
)
+
+GR_PYTHON_INSTALL(
+ FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/__init__.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/constants.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/ControlPort.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/ControlPort-remote
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/StreamReceiver.py
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/StreamReceiver-remote
+ ${CMAKE_CURRENT_BINARY_DIR}/GNURadio/ttypes.py
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/ctrlport/GNURadio
+ COMPONENT "runtime_python"
+)
+
+endif(THRIFT_FOUND)
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py
new file mode 100644
index 0000000000..87d2cf5658
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py
@@ -0,0 +1,132 @@
+#
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+"""
+Python Client classes for interfacing with the GNU Radio ControlPort interface
+and for accessing Performance Counters.
+
+While ControlPort and these client classes are designed to support multiple
+Remote Procedure Call (RPC) transports, the Apache Thrift middle-ware RPC
+is currently the only supported transport.
+
+"""
+
+import exceptions
+
+"""
+GNURadioControlPortClient is the main class for creating a GNU Radio
+ControlPort client application for all transports.
+
+Two constructors are provided for creating a connection to ControlPort.
+
+"""
+
+class GNURadioControlPortClient():
+ """
+ Constructor for creating a ControlPort connection to a specified host / port
+
+ Args:
+ host: hostname of the connection. Specifying None (default) will
+ select the loopback interface.
+
+ port: port number to use for the connection. Specifying None (default)
+ will select the specified RPC transport's default port number, if
+ the transport has a default.
+
+ rpcmethod: This string specifies the RPC transport to use for the
+ client connection. The default implementation currently uses
+ the Apache Thrift RPC transport. The value specified here must
+ be one of the transport keys listed in the RPCMethods dictionary
+ above
+
+ callback: This optional parameter is a callback function that will be passed
+ a reference to the Client implementation for the RPC transport specified
+ by rpcmethod. The callback will be executed after the client has been
+ constructed, but before __init__ returns.
+
+ blockingcallback: This optional parameter is a callback function with
+ no parameters that will be executed after callback() is executed,
+ but before __init__ returns. It is useful if your application
+ requires that a blocking function be called to start the application,
+ such as QtGui.QApplication.exec_
+
+ """
+
+ def __init__(self, host = None, port = None, rpcmethod = 'thrift', callback = None, blockingcallback = None):
+ __init__([host, port], rpcmethod, callback, blockingcallback)
+
+ """
+ Constructor for creating a ControlPort from a tuple of command line arguments (i.e. sys.argv)
+
+ Args:
+ argv: List of command line arguments. Future implementations may parse the argument list
+ for OptionParser style key / value pairs, however the current implementation
+ simply takes argv[1] and argv[2] as the connection hostname and port, respectively.
+
+ Example Usage:
+
+ In the following QT client example, the ControlPort host and port are specified to
+ the Client application as the first two command line arguments. The MAINWindow class is
+ of the type QtGui.QMainWindow, and is the main window for the QT application. MyApp
+ is a simple helper class for starting the application.
+
+ class MAINWindow(QtGui.QMainWindow):
+ ... QT Application implementation ...
+
+ class MyApp(object):
+ def __init__(self, args):
+ from GNURadioControlPortClient import GNURadioControlPortClient
+ GNURadioControlPortClient(args, 'thrift', self.run, QtGui.QApplication(sys.argv).exec_)
+
+ def run(self, client):
+ MAINWindow(client).show()
+
+ MyApp(sys.argv)
+
+
+ """
+
+ def __init__(self, argv = [], rpcmethod = 'thrift', callback = None, blockingcallback = None):
+ if len(argv) > 1: host = argv[1]
+ else: host = None
+
+ if len(argv) > 2: port = argv[2]
+ else: port = None
+
+ self.client = None
+
+ from gnuradio.ctrlport.RPCConnection import RPCMethods
+ if RPCMethods.has_key(rpcmethod):
+ from gnuradio.ctrlport.RPCConnectionThrift import RPCConnectionThrift
+ if rpcmethod == 'thrift':
+ #print("making RPCConnectionThrift")
+ self.client = RPCConnectionThrift(host, port)
+ #print("made %s" % self.client)
+
+ #print("making callback call")
+ if not callback is None:
+ callback(self.client)
+
+ #print("making blockingcallback call")
+ if not blockingcallback is None:
+ blockingcallback()
+ else:
+ print("Unsupported RPC method: ", rpcmethod)
+ raise exceptions.ValueError()
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py
index 661705d613..c5bfd0a8cb 100644
--- a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py
@@ -23,7 +23,7 @@
from gnuradio import gr
from gnuradio import blocks
from gnuradio import filter
-from gnuradio.ctrlport import GNURadio
+from gnuradio.ctrlport.GNURadio import ControlPort
import sys, time, struct
try:
@@ -442,7 +442,7 @@ class GrDataPlotterValueTable:
units = str(knobprops[itemKey].units)
descr = str(knobprops[itemKey].description)
- if(type(v) == GNURadio.complex):
+ if(type(v) == ControlPort.complex):
v = v.re + v.im*1j
# If it's a byte stream, Python thinks it's a string.
# Unpack and convert to floats for plotting.
@@ -468,7 +468,7 @@ class GrDataPlotterValueTable:
for k in knobs.keys():
if k not in foundKeys:
v = knobs[k].value
- if(type(v) == GNURadio.complex):
+ if(type(v) == ControlPort.complex):
v = v.re + v.im*1j
# If it's a byte stream, Python thinks it's a string.
# Unpack and convert to floats for plotting.
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py
new file mode 100644
index 0000000000..e14cc0cea7
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py
@@ -0,0 +1,115 @@
+#
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+import exceptions
+
+"""
+RPCMethods is a dictionary listing RPC transports currently supported
+by this client.
+
+Args:
+ function: the function whose parameter list will be examined
+ excluded_args: function arguments that are NOT to be added to the dictionary (sequence of strings)
+ options: result of command argument parsing (optparse.Values)
+"""
+
+RPCMethods = {'thrift': 'Apache Thrift',
+ #'ice': 'Zeroc ICE'
+ }
+
+
+"""
+Base class for RPC transport clients
+
+Methods that all RPC clients should implement include:
+
+ def newConnection(host,port): Method for re-establishing a new client
+ connection to a different host / port
+
+ def properties([]): Given a list of ControlPort property names,
+ or an empty list to specify all currently registered properties,
+ this method returns a dictionary of metadata describing the
+ the specified properties. The dictionary key contains the name
+ of each returned properties.
+
+ def getKnobs([]): Given a list of ControlPort property names,
+ or an empty list to specify all currently registered properties,
+ this method returns a dictionary of the current value of
+ the specified properties.
+
+ def getRe([]): Given a list of regular expression strings,
+ this method returns a dictionary of the current value of
+ the all properties with names that match the specified
+ expressions.
+
+ def setKnobs({}): Given a dictionary of ControlPort property
+ key / value pairs, this method requests that ControlPort
+ attempt to set the specified named properties to the
+ value given. Success in setting each property to the
+ value specified requires that the property be registered
+ as a 'setable' ControlPort property, that the client have the
+ requisite privilege level to set the property, and
+ the underlying Block's implementation in handling
+ the set request.
+
+Args:
+ method: name of the RPC transport
+ port: port number of the connection
+ host: hostname of the connection
+"""
+
+class RPCConnection(object):
+ def __init__(self, method, port, host=None):
+ (self.method, self.port) = (method, port)
+ if host is None: self.host = '127.0.0.1'
+ else: self.host = host
+
+ def __str__(self):
+ return "%s connection on %s:%s"%(self.getName(), self.getHost(), self.getPort())
+
+ def getName(self):
+ return RPCMethods[self.method]
+
+ def getHost(self):
+ return self.host
+
+ def getPort(self):
+ return self.port
+
+ def newConnection(self, host=None, port=None):
+ raise exceptions.NotImplementedError()
+
+ def properties(self, *args):
+ raise exceptions.NotImplementedError()
+
+ def getKnobs(self, *args):
+ raise exceptions.NotImplementedError()
+
+ def getRe(self,*args):
+ raise exceptions.NotImplementedError()
+
+ def setKnobs(self,*args):
+ raise exceptions.NotImplementedError()
+
+ def shutdown(self):
+ raise exceptions.NotImplementedError()
+
+ def printProperties(self, props):
+ raise exceptions.NotImplementedError()
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py
new file mode 100644
index 0000000000..9a2a302af5
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from thrift import Thrift
+from thrift.transport import TSocket
+from thrift.transport import TTransport
+from thrift.protocol import TBinaryProtocol
+from gnuradio.ctrlport.GNURadio import ControlPort
+from gnuradio.ctrlport import RPCConnection
+from gnuradio import gr
+import sys
+
+class ThriftRadioClient:
+ def __init__(self, host, port):
+ self.tsocket = TSocket.TSocket(host, port)
+ self.transport = TTransport.TBufferedTransport(self.tsocket)
+ self.protocol = TBinaryProtocol.TBinaryProtocol(self.transport)
+
+ self.radio = ControlPort.Client(self.protocol)
+ self.transport.open()
+
+ def __del__(self):
+ self.radio.shutdown()
+ self.transport.close()
+
+ def getRadio(self, host, port):
+ return self.radio
+
+"""
+RPC Client interface for the Apache Thrift middle-ware RPC transport.
+
+Args:
+ port: port number of the connection
+ host: hostname of the connection
+"""
+
+class RPCConnectionThrift(RPCConnection.RPCConnection):
+ class Knob():
+ def __init__(self, key, value=None, ktype=0):
+ (self.key, self.value, self.ktype) = (key, value, ktype)
+
+ def __repr__(self):
+ return "({0} = {1})".format(self.key, self.value)
+
+ def __init__(self, host=None, port=None):
+ from gnuradio.ctrlport.GNURadio import ttypes
+ self.BaseTypes = ttypes.BaseTypes
+ self.KnobBase = ttypes.KnobBase
+
+ # If not set by the user, get the port number from the thrift
+ # config file, if one is set. Defaults to 9090 otherwise.
+ if port is None:
+ p = gr.prefs()
+ thrift_config_file = p.get_string("ControlPort", "config", "");
+ if(len(thrift_config_file) > 0):
+ p.add_config_file(thrift_config_file)
+ port = p.get_long("thrift", "port", 9090)
+ else:
+ port = 9090
+ else:
+ port = int(port)
+
+ super(RPCConnectionThrift, self).__init__(method='thrift', port=port, host=host)
+ self.newConnection(host, port)
+
+ self.unpack_dict = {
+ self.BaseTypes.BOOL: lambda k,b: self.Knob(k, b.value.a_bool, self.BaseTypes.BOOL),
+ self.BaseTypes.BYTE: lambda k,b: self.Knob(k, b.value.a_byte, self.BaseTypes.BYTE),
+ self.BaseTypes.SHORT: lambda k,b: self.Knob(k, b.value.a_short, self.BaseTypes.SHORT),
+ self.BaseTypes.INT: lambda k,b: self.Knob(k, b.value.a_int, self.BaseTypes.INT),
+ self.BaseTypes.LONG: lambda k,b: self.Knob(k, b.value.a_long, self.BaseTypes.LONG),
+ self.BaseTypes.DOUBLE: lambda k,b: self.Knob(k, b.value.a_double, self.BaseTypes.DOUBLE),
+ self.BaseTypes.STRING: lambda k,b: self.Knob(k, b.value.a_string, self.BaseTypes.STRING),
+ self.BaseTypes.COMPLEX: lambda k,b: self.Knob(k, b.value.a_complex, self.BaseTypes.COMPLEX),
+ self.BaseTypes.F32VECTOR: lambda k,b: self.Knob(k, b.value.a_f32vector, self.BaseTypes.F32VECTOR),
+ self.BaseTypes.F64VECTOR: lambda k,b: self.Knob(k, b.value.a_f64vector, self.BaseTypes.F64VECTOR),
+ self.BaseTypes.S64VECTOR: lambda k,b: self.Knob(k, b.value.a_s64vector, self.BaseTypes.S64VECTOR),
+ self.BaseTypes.S32VECTOR: lambda k,b: self.Knob(k, b.value.a_s32vector, self.BaseTypes.S32VECTOR),
+ self.BaseTypes.S16VECTOR: lambda k,b: self.Knob(k, b.value.a_s16vector, self.BaseTypes.S16VECTOR),
+ self.BaseTypes.S8VECTOR: lambda k,b: self.Knob(k, b.value.a_s8vector, self.BaseTypes.S8VECTOR),
+ self.BaseTypes.C32VECTOR: lambda k,b: self.Knob(k, b.value.a_c32vector, self.BaseTypes.C32VECTOR),
+ }
+
+ self.pack_dict = {
+ self.BaseTypes.BOOL: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_bool = k.value)),
+ self.BaseTypes.BYTE: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_byte = k.value)),
+ self.BaseTypes.SHORT: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_short = k.value)),
+ self.BaseTypes.INT: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_int = k.value)),
+ self.BaseTypes.LONG: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_long = k.value)),
+ self.BaseTypes.DOUBLE: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_double = k.value)),
+ self.BaseTypes.STRING: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_string = k.value)),
+ self.BaseTypes.COMPLEX: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_complex = k.value)),
+ self.BaseTypes.F32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_f32vector = k.value)),
+ self.BaseTypes.F64VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_f64vector = k.value)),
+ self.BaseTypes.S64VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s64vector = k.value)),
+ self.BaseTypes.S32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s32vector = k.value)),
+ self.BaseTypes.S16VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s16vector = k.value)),
+ self.BaseTypes.S8VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_s8vector = k.value)),
+ self.BaseTypes.C32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_c32vector = k.value)),
+ }
+
+ def unpackKnob(self, key, knob):
+ f = self.unpack_dict.get(knob.type, None)
+ if(f):
+ return f(key, knob)
+ else:
+ sys.stderr.write("unpackKnobs: Incorrect Knob type: {0}\n".format(knob.type))
+ raise exceptions.ValueError
+
+ def packKnob(self, knob):
+ f = self.pack_dict.get(knob.ktype, None)
+ if(f):
+ return f(knob)
+ else:
+ sys.stderr.write("packKnobs: Incorrect Knob type: {0}\n".format(knob.type))
+ raise exceptions.ValueError
+
+ def newConnection(self, host=None, port=None):
+ try:
+ self.thriftclient = ThriftRadioClient(self.getHost(), self.getPort())
+ except TTransport.TTransportException:
+ sys.stderr.write("Could not connect to ControlPort endpoint at {0}:{1}.\n\n".format(host, port))
+ sys.exit(1)
+
+ def properties(self, *args):
+ knobprops = self.thriftclient.radio.properties(*args)
+ for key, knobprop in knobprops.iteritems():
+ #print("key:", key, "value:", knobprop, "type:", knobprop.type)
+ knobprops[key].min = self.unpackKnob(key, knobprop.min)
+ knobprops[key].max = self.unpackKnob(key, knobprop.max)
+ knobprops[key].defaultvalue = self.unpackKnob(key, knobprop.defaultvalue)
+ return knobprops
+
+ def getKnobs(self, *args):
+ result = {}
+ for key, knob in self.thriftclient.radio.getKnobs(*args).iteritems():
+ #print("key:", key, "value:", knob, "type:", knob.type)
+ result[key] = self.unpackKnob(key, knob)
+
+ # If complex, convert to Python complex
+ # FIXME: better list iterator way to handle this?
+ if(knob.type == self.BaseTypes.C32VECTOR):
+ for i in xrange(len(result[key].value)):
+ result[key].value[i] = complex(result[key].value[i].re,
+ result[key].value[i].im)
+ return result
+
+ def getKnobsRaw(self, *args):
+ result = {}
+ for key, knob in self.thriftclient.radio.getKnobs(*args).iteritems():
+ #print("key:", key, "value:", knob, "type:", knob.type)
+ result[key] = knob
+ return result
+
+ def getRe(self,*args):
+ result = {}
+ for key, knob in self.thriftclient.radio.getRe(*args).iteritems():
+ result[key] = self.unpackKnob(key, knob)
+ return result
+
+ def setKnobs(self, *args):
+ if(type(*args) == dict):
+ a = dict(*args)
+ result = {}
+ for key, knob in a.iteritems():
+ result[key] = self.packKnob(knob)
+ self.thriftclient.radio.setKnobs(result)
+ elif(type(*args) == list or type(*args) == tuple):
+ a = list(*args)
+ result = {}
+ for k in a:
+ result[k.key] = self.packKnob(k)
+ self.thriftclient.radio.setKnobs(result)
+ else:
+ sys.stderr.write("setKnobs: Invalid type; must be dict, list, or tuple\n")
+
+ def shutdown(self):
+ self.thriftclient.radio.shutdown()
+
+ def printProperties(self, props):
+ info = ""
+ info += "Item:\t\t{0}\n".format(props.description)
+ info += "units:\t\t{0}\n".format(props.units)
+ info += "min:\t\t{0}\n".format(props.min.value)
+ info += "max:\t\t{0}\n".format(props.max.value)
+ info += "default:\t\t{0}\n".format(props.defaultvalue.value)
+ info += "Type Code:\t0x{0:x}\n".format(props.type)
+ info += "Disp Code:\t0x{0:x}\n".format(props.display)
+ return info
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor
new file mode 100644
index 0000000000..c866776355
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor
@@ -0,0 +1,771 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from PyQt4 import QtCore,Qt
+import PyQt4.QtGui as QtGui
+import os, sys, time, struct
+
+from gnuradio import gr, ctrlport
+from gnuradio.ctrlport.GrDataPlotter import *
+
+class RateDialog(QtGui.QDialog):
+ def __init__(self, delay, parent=None):
+ super(RateDialog, self).__init__(parent)
+ self.gridLayout = QtGui.QGridLayout(self)
+ self.setWindowTitle("Update Delay (ms)");
+ self.delay = QtGui.QLineEdit(self);
+ self.delay.setText(str(delay));
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
+ self.gridLayout.addWidget(self.delay);
+ self.gridLayout.addWidget(self.buttonBox);
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+ def accept(self):
+ self.done(1);
+ def reject(self):
+ self.done(0);
+
+class MAINWindow(QtGui.QMainWindow):
+ def minimumSizeHint(self):
+ return Qtgui.QSize(800,600)
+
+ def __init__(self, radioclient):
+
+ super(MAINWindow, self).__init__()
+ self.radioclient = radioclient
+ self.updateRate = 1000;
+ self.conns = []
+ self.plots = []
+ self.knobprops = []
+
+ self.mdiArea = QtGui.QMdiArea()
+ self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.setCentralWidget(self.mdiArea)
+
+ self.mdiArea.subWindowActivated.connect(self.updateMenus)
+ self.windowMapper = QtCore.QSignalMapper(self)
+ self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow)
+
+ self.createActions()
+ self.createMenus()
+ self.createToolBars()
+ self.createStatusBar()
+ self.updateMenus()
+
+ self.setWindowTitle("GNU Radio Control Port Monitor")
+ self.setUnifiedTitleAndToolBarOnMac(True)
+
+ self.newCon(radioclient)
+ icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
+ self.setWindowIcon(icon)
+
+ # Locally turn off ControlPort export from GR. This prevents
+ # our GR-based plotters from launching their own ControlPort
+ # instance (and possibly causing a port collision if one has
+ # been specified).
+ os.environ['GR_CONF_CONTROLPORT_ON'] = 'False'
+
+ def setUpdateRate(self,nur):
+ self.updateRate = int(nur);
+ for c in self.conns:
+ c.updateRate = self.updateRate;
+ c.timer.setInterval(self.updateRate);
+
+ def newCon(self, csomeBool):
+ child = MForm(self.radioclient, len(self.conns), parent = self, dialogprompt = not csomeBool)
+ if(child.radioclient is not None):
+ child.setWindowTitle(str(child.radioclient))
+ self.mdiArea.addSubWindow(child)
+ self.mdiArea.currentSubWindow().showMaximized()
+ self.conns.append(child)
+ self.plots.append([])
+
+ def propertiesMenu(self, key, radio, uid):
+ title = str(radio)
+
+ props = radio.properties([key])
+
+ pmin,pmax = get_minmax(props[key])
+
+ # Use display option mask of item to set up available plot
+ # types and default options.
+ disp = self.knobprops[uid][key].display
+ cplx = disp & gr.DISPOPTCPLX | disp & gr.DISPXY
+ strip = disp & gr.DISPOPTSTRIP
+ stem = disp & gr.DISPOPTSTEM
+ log = disp & gr.DISPOPTLOG
+ scatter = disp & gr.DISPOPTSCATTER
+
+ def newUpdaterProxy():
+ self.newUpdater(key, radio)
+
+ def newPlotterFProxy():
+ self.newPlotF(key, uid, title, pmin, pmax,
+ log, strip, stem)
+
+ def newPlotterCProxy():
+ self.newPlotC(key, uid, title, pmin, pmax,
+ log, strip, stem)
+
+ def newPlotterConstProxy():
+ self.newPlotConst(key, uid, title, pmin, pmax,
+ scatter, strip)
+
+ def newPlotterPsdFProxy():
+ self.newPlotPsdF(key, uid, title)
+
+ def newPlotterPsdCProxy():
+ self.newPlotPsdC(key, uid, title)
+
+ def newPlotterRasterFProxy():
+ self.newPlotRasterF(key, uid, title, pmin, pmax)
+
+ def newPlotterRasterBProxy():
+ self.newPlotRasterB(key, uid, title, pmin, pmax)
+
+ menu = QtGui.QMenu(self)
+ menu.setTitle("Item Actions")
+ menu.setTearOffEnabled(False)
+
+ # object properties
+ menu.addAction("Properties", newUpdaterProxy)
+
+ # displays available
+ if(cplx == 0):
+ menu.addAction("Plot Time", newPlotterFProxy)
+ menu.addAction("Plot PSD", newPlotterPsdFProxy)
+ menu.addAction("Plot Raster (real)", newPlotterRasterFProxy)
+ #menu.addAction("Plot Raster (bits)", newPlotterRasterBProxy)
+ else:
+ menu.addAction("Plot Time", newPlotterCProxy)
+ menu.addAction("Plot PSD", newPlotterPsdCProxy)
+ menu.addAction("Plot Constellation", newPlotterConstProxy)
+
+ menu.popup(QtGui.QCursor.pos())
+
+ def newUpdater(self, key, radio):
+ updater = UpdaterWindow(key, radio, None)
+ updater.setWindowTitle("Updater: " + key)
+ updater.setModal(False)
+ updater.exec_()
+
+ def newSub(self, e):
+ tag = str(e.text(0))
+ tree = e.treeWidget().parent()
+ uid = tree.uid
+ knobprop = self.knobprops[uid][tag]
+
+ strr = str(tree.radioclient)
+ print(strr)
+# r = strr.split(" ")
+ title = strr #title = "{0}:{1}".format(r[3], r[5])
+ pmin,pmax = get_minmax(knobprop)
+
+ disp = knobprop.display
+ if(disp & gr.DISPTIME):
+ strip = disp & gr.DISPOPTSTRIP
+ stem = disp & gr.DISPOPTSTEM
+ log = disp & gr.DISPOPTLOG
+ if(disp & gr.DISPOPTCPLX == 0):
+ self.newPlotF(tag, uid, title, pmin, pmax,
+ log, strip, stem)
+ else:
+ self.newPlotC(tag, uid, title, pmin, pmax,
+ log, strip, stem)
+
+ elif(disp & gr.DISPXY):
+ scatter = disp & gr.DISPOPTSCATTER
+ self.newPlotConst(tag, uid, title, pmin, pmax, scatter)
+
+ elif(disp & gr.DISPPSD):
+ if(disp & gr.DISPOPTCPLX == 0):
+ self.newPlotPsdF(tag, uid, title)
+ else:
+ self.newPlotPsdC(tag, uid, title)
+
+ def startDrag(self, e):
+ drag = QtGui.QDrag(self)
+ mime_data = QtCore.QMimeData()
+
+ tag = str(e.text(0))
+ tree = e.treeWidget().parent()
+ knobprop = self.knobprops[tree.uid][tag]
+ disp = knobprop.display
+ iscomplex = (disp & gr.DISPOPTCPLX) or (disp & gr.DISPXY)
+
+ if(disp != gr.DISPNULL):
+ data = "PlotData:::{0}:::{1}".format(tag, iscomplex)
+ else:
+ data = "OtherData:::{0}:::{1}".format(tag, iscomplex)
+
+ mime_data.setText(data)
+ drag.setMimeData(mime_data)
+
+ drop = drag.start()
+
+ def createPlot(self, plot, uid, title):
+ plot.start()
+ self.plots[uid].append(plot)
+
+ self.mdiArea.addSubWindow(plot)
+ plot.setWindowTitle("{0}: {1}".format(title, plot.name()))
+ self.connect(plot.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+
+ # when the plot is updated via drag-and-drop, we need to be
+ # notified of the new qwidget that's created so we can
+ # properly destroy it.
+ plot.plotupdated.connect(self.plotUpdated)
+
+ plot.show()
+
+ def plotUpdated(self, q):
+ # the plot has been updated with a new qwidget; make sure this
+ # gets dies to the destroyPlot function.
+ for i, plots in enumerate(self.plots):
+ for p in plots:
+ if(p == q):
+ #plots.remove(p)
+ #plots.append(q)
+ self.connect(q.qwidget(),
+ QtCore.SIGNAL('destroyed(QObject*)'),
+ self.destroyPlot)
+ break
+
+ def destroyPlot(self, obj):
+ for plots in self.plots:
+ for p in plots:
+ if p.qwidget() == obj:
+ plots.remove(p)
+ break
+
+ def newPlotConst(self, tag, uid, title="", pmin=None, pmax=None,
+ scatter=False, stripchart=False):
+ plot = GrDataPlotterConst(tag, 32e6, pmin, pmax, stripchart)
+ plot.scatter(scatter)
+ self.createPlot(plot, uid, title)
+
+ def newPlotF(self, tag, uid, title="", pmin=None, pmax=None,
+ logy=False, stripchart=False, stem=False):
+ plot = GrDataPlotterF(tag, 32e6, pmin, pmax, stripchart)
+ plot.semilogy(logy)
+ plot.stem(stem)
+ self.createPlot(plot, uid, title)
+
+ def newPlotC(self, tag, uid, title="", pmin=None, pmax=None,
+ logy=False, stripchart=False, stem=False):
+ plot = GrDataPlotterC(tag, 32e6, pmin, pmax, stripchart)
+ plot.semilogy(logy)
+ plot.stem(stem)
+ self.createPlot(plot, uid, title)
+
+ def newPlotPsdF(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrDataPlotterPsdF(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotPsdC(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrDataPlotterPsdC(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotRasterF(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrTimeRasterF(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def newPlotRasterB(self, tag, uid, title="", pmin=None, pmax=None):
+ plot = GrTimeRasterB(tag, 32e6, pmin, pmax)
+ self.createPlot(plot, uid, title)
+
+ def update(self, knobs, uid):
+ #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
+ for plot in self.plots[uid]:
+ data = []
+ for n in plot.knobnames:
+ d = knobs[n].value
+ # TODO: FIX COMPLEX!
+# if(type(d) == GNURadio.complex):
+# d = [d.re, d.im]
+
+ # If it's a byte stream, Python thinks it's a string.
+ # Unpack and convert to floats for plotting.
+ if(type(d) == str and n.find('probe2_b') == 0):
+ d = struct.unpack(len(d)*'b', d)
+ d = [float(di) for di in d]
+
+ data.append(d)
+ plot.update(data)
+ plot.stop()
+ plot.wait()
+ plot.start()
+
+ def setActiveSubWindow(self, window):
+ if window:
+ self.mdiArea.setActiveSubWindow(window)
+
+
+ def createActions(self):
+ self.newConAct = QtGui.QAction("&New Connection",
+ self, shortcut=QtGui.QKeySequence.New,
+ statusTip="Create a new file", triggered=self.newCon)
+
+ self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q",
+ statusTip="Exit the application",
+ triggered=QtGui.qApp.closeAllWindows)
+
+ self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4",
+ statusTip="Close the active window",
+ triggered=self.mdiArea.closeActiveSubWindow)
+
+ self.closeAllAct = QtGui.QAction("Close &All", self,
+ statusTip="Close all the windows",
+ triggered=self.mdiArea.closeAllSubWindows)
+
+ self.urAct = QtGui.QAction("Update Rate", self, shortcut="F5",
+ statusTip="Change Update Rate",
+ triggered=self.updateRateShow)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T);
+ self.tileAct = QtGui.QAction("&Tile", self,
+ statusTip="Tile the windows",
+ triggered=self.mdiArea.tileSubWindows,
+ shortcut=qks)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C);
+ self.cascadeAct = QtGui.QAction("&Cascade", self,
+ statusTip="Cascade the windows", shortcut=qks,
+ triggered=self.mdiArea.cascadeSubWindows)
+
+ self.nextAct = QtGui.QAction("Ne&xt", self,
+ shortcut=QtGui.QKeySequence.NextChild,
+ statusTip="Move the focus to the next window",
+ triggered=self.mdiArea.activateNextSubWindow)
+
+ self.previousAct = QtGui.QAction("Pre&vious", self,
+ shortcut=QtGui.QKeySequence.PreviousChild,
+ statusTip="Move the focus to the previous window",
+ triggered=self.mdiArea.activatePreviousSubWindow)
+
+ self.separatorAct = QtGui.QAction(self)
+ self.separatorAct.setSeparator(True)
+
+ self.aboutAct = QtGui.QAction("&About", self,
+ statusTip="Show the application's About box",
+ triggered=self.about)
+
+ self.aboutQtAct = QtGui.QAction("About &Qt", self,
+ statusTip="Show the Qt library's About box",
+ triggered=QtGui.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.newConAct)
+ self.fileMenu.addAction(self.urAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.windowMenu = self.menuBar().addMenu("&Window")
+ self.updateWindowMenu()
+ self.windowMenu.aboutToShow.connect(self.updateWindowMenu)
+
+ self.menuBar().addSeparator()
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def updateRateShow(self):
+ askrate = RateDialog(self.updateRate, self);
+ if askrate.exec_():
+ ur = float(str(askrate.delay.text()));
+ self.setUpdateRate(ur);
+ return;
+ else:
+ return;
+
+ def createToolBars(self):
+ self.fileToolBar = self.addToolBar("File")
+ self.fileToolBar.addAction(self.newConAct)
+ self.fileToolBar.addAction(self.urAct)
+
+ self.fileToolBar = self.addToolBar("Window")
+ self.fileToolBar.addAction(self.tileAct)
+ self.fileToolBar.addAction(self.cascadeAct)
+
+ def createStatusBar(self):
+ self.statusBar().showMessage("Ready")
+
+
+ def activeMdiChild(self):
+ activeSubWindow = self.mdiArea.activeSubWindow()
+ if activeSubWindow:
+ return activeSubWindow.widget()
+ return None
+
+ def updateMenus(self):
+ hasMdiChild = (self.activeMdiChild() is not None)
+ self.closeAct.setEnabled(hasMdiChild)
+ self.closeAllAct.setEnabled(hasMdiChild)
+ self.tileAct.setEnabled(hasMdiChild)
+ self.cascadeAct.setEnabled(hasMdiChild)
+ self.nextAct.setEnabled(hasMdiChild)
+ self.previousAct.setEnabled(hasMdiChild)
+ self.separatorAct.setVisible(hasMdiChild)
+
+ def updateWindowMenu(self):
+ self.windowMenu.clear()
+ self.windowMenu.addAction(self.closeAct)
+ self.windowMenu.addAction(self.closeAllAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.tileAct)
+ self.windowMenu.addAction(self.cascadeAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.nextAct)
+ self.windowMenu.addAction(self.previousAct)
+ self.windowMenu.addAction(self.separatorAct)
+
+ def about(self):
+ about_info = \
+'''Copyright 2012 Free Software Foundation, Inc.\n
+This program is part of GNU Radio.\n
+GNU Radio is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.\n
+GNU Radio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n
+You should have received a copy of the GNU General Public License along with GNU Radio; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.'''
+
+ QtGui.QMessageBox.about(None, "gr-ctrlport-monitor", about_info)
+
+
+class ConInfoDialog(QtGui.QDialog):
+ def __init__(self, parent=None):
+ super(ConInfoDialog, self).__init__(parent)
+
+ self.gridLayout = QtGui.QGridLayout(self)
+
+
+ self.host = QtGui.QLineEdit(self);
+ self.port = QtGui.QLineEdit(self);
+ self.host.setText("localhost");
+ self.port.setText("43243");
+
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
+
+ self.gridLayout.addWidget(self.host);
+ self.gridLayout.addWidget(self.port);
+ self.gridLayout.addWidget(self.buttonBox);
+
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+
+ def accept(self):
+ self.done(1);
+
+ def reject(self):
+ self.done(0);
+
+
+class UpdaterWindow(QtGui.QDialog):
+ def __init__(self, key, radio, parent):
+ QtGui.QDialog.__init__(self, parent)
+
+ self.key = key;
+ self.radio = radio
+
+ self.resize(300,200)
+ self.layout = QtGui.QVBoxLayout()
+
+ self.props = radio.properties([key])[key]
+ info = radio.printProperties(self.props)
+
+ self.infoLabel = QtGui.QLabel(info)
+ self.layout.addWidget(self.infoLabel)
+
+ # Test here to make sure that a 'set' function exists
+ try:
+ radio.setKnobs(radio.getKnobs([key]))
+ has_set = True
+ except:
+ has_set = False
+
+
+ if(has_set is False):
+ self.cancelButton = QtGui.QPushButton("Ok")
+ self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject)
+
+ self.buttonlayout = QtGui.QHBoxLayout()
+ self.buttonlayout.addWidget(self.cancelButton)
+ self.layout.addLayout(self.buttonlayout)
+
+ else: # we have a set function
+ self.textInput = QtGui.QLineEdit()
+ self.layout.addWidget(self.textInput)
+
+ self.applyButton = QtGui.QPushButton("Apply")
+ self.setButton = QtGui.QPushButton("OK")
+ self.cancelButton = QtGui.QPushButton("Cancel")
+
+ rv = radio.getKnobs([key])
+ val = rv[key].value
+ if(type(val) == ControlPort.complex):
+ val = val.re + val.im*1j
+
+ self.textInput.setText(str(val))
+ self.sv = rv[key]
+
+ self.applyButton.connect(self.applyButton, QtCore.SIGNAL('clicked()'), self._apply)
+ self.setButton.connect(self.setButton, QtCore.SIGNAL('clicked()'), self._set)
+ self.cancelButton.connect(self.cancelButton, QtCore.SIGNAL('clicked()'), self.reject)
+
+ self.is_num = ((type(self.sv.value)==float) or (type(self.sv.value)==int))
+ if(self.is_num):
+ self.sliderlayout = QtGui.QHBoxLayout()
+
+ self.slider = QtGui.QSlider(QtCore.Qt.Horizontal)
+
+ self.sliderlayout.addWidget(QtGui.QLabel(str(self.props.min.value)))
+ self.sliderlayout.addWidget(self.slider)
+ self.sliderlayout.addWidget(QtGui.QLabel(str(self.props.max.value)))
+
+ self.steps = 10000
+ self.valspan = self.props.max.value - self.props.min.value
+
+ self.slider.setRange(0, 10000)
+ self._set_slider_value(self.sv.value)
+
+ self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"), self._slide)
+
+ self.layout.addLayout(self.sliderlayout)
+ else:
+ self._set_slider_value = None
+
+ self.buttonlayout = QtGui.QHBoxLayout()
+ self.buttonlayout.addWidget(self.applyButton)
+ self.buttonlayout.addWidget(self.setButton)
+ self.buttonlayout.addWidget(self.cancelButton)
+ self.layout.addLayout(self.buttonlayout)
+
+ # set layout and go...
+ self.setLayout(self.layout)
+
+ def _set_slider_value(self, val):
+ self.slider.setValue(self.steps*(val-self.props.min.value)/self.valspan)
+
+ def _slide(self):
+ val = (self.slider.value()*self.valspan + self.props.min.value)/float(self.steps)
+ self.textInput.setText(str(val))
+
+ def _apply(self):
+ if(type(self.sv.value) == str):
+ val = str(self.textInput.text())
+ elif(type(self.sv.value) == int):
+ val = int(round(float(self.textInput.text())))
+ elif(type(self.sv.value) == float):
+ val = float(self.textInput.text())
+ elif(type(self.sv.value) == ControlPort.complex):
+ t = str(self.textInput.text())
+ t = complex(t.strip("(").strip(")").replace(" ", ""))
+ val = ControlPort.complex()
+ val.re = t.real
+ val.im = t.imag
+ else:
+ sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value)))
+ return
+
+ self.sv.value = val
+ km = {}
+ km[self.key] = self.sv
+ self.radio.setKnobs(km)
+ if self._set_slider_value:
+ self._set_slider_value(self.sv.value)
+
+ def _set(self):
+ self._apply()
+ self.done(0)
+
+
+class MForm(QtGui.QWidget):
+ def update(self):
+ # TODO: revisit this try-except block, figure out what it's doing, and if we need to keep it. at very lease makes debugging dificult
+ if True: #try:
+ st = time.time();
+ knobs = self.radioclient.getKnobs([])
+ ft = time.time();
+ latency = ft-st;
+ self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%(latency*1000))
+
+# except Exception, e:
+# sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e))
+# if(type(self.parent) is MAINWindow):
+# # Find window of connection
+# remove = []
+# for p in self.parent.mdiArea.subWindowList():
+# if self.parent.conns[self.uid] == p.widget():
+# remove.append(p)
+#
+# # Find any subplot windows of connection
+# for p in self.parent.mdiArea.subWindowList():
+# for plot in self.parent.plots[self.uid]:
+# if plot.qwidget() == p.widget():
+# remove.append(p)
+#
+# # Clean up local references to these
+# self.parent.conns.remove(self.parent.conns[self.uid])
+# self.parent.plots.remove(self.parent.plots[self.uid])
+#
+# # Remove subwindows for connection and plots
+# for r in remove:
+# self.parent.mdiArea.removeSubWindow(r)
+#
+# # Clean up self
+# self.close()
+# else:
+# sys.exit(1)
+# return
+
+ tableitems = knobs.keys()
+
+ #UPDATE TABLE:
+ #try:
+ self.table.updateItems(knobs, self.knobprops)
+ #except:
+ # self.knobprops = self.radioclient.properties([])
+ # print("knobsprops1:", len(self.knobprops))
+
+ #UPDATE PLOTS
+ self.parent.update(knobs, self.uid)
+
+
+ def __init__(self, radioclient, uid=0, updateRate=2000, parent=None, dialogprompt = False):
+
+ super(MForm, self).__init__()
+ self.radioclient = radioclient
+# print("before radioclient.getHost()", radioclient.getHost(), radioclient.getPort(), "prompt", prompt)
+ if(dialogprompt or radioclient.getHost() is None or radioclient.getPort() is None):
+# print("before ConInfoDialog")
+ askinfo = ConInfoDialog(self);
+ if askinfo.exec_():
+ host = str(askinfo.host.text());
+ port = str(askinfo.port.text());
+# print("before radioclient.newConnection host: %s port: %s"%(host,port))
+ newradio = self.radioclient.newConnection(host, port)
+ if newradio is None:
+ print("Error making a %s connection to %s:%s from %s" % (radioclient.getName(), host, port, radioclient))
+ else:
+ self.radioclient = newradio
+
+ else:
+ self.radioclient = Nonclient = None
+ return
+
+
+ self.uid = uid
+ self.parent = parent
+ self.horizontalLayout = QtGui.QVBoxLayout(self)
+ self.gridLayout = QtGui.QGridLayout()
+
+ self.knobprops = self.radioclient.properties([])
+ #print("props5:", self.knobprops)
+ self.parent.knobprops.append(self.knobprops)
+ self.resize(775,500)
+ self.timer = QtCore.QTimer()
+ self.constupdatediv = 0
+ self.tableupdatediv = 0
+ plotsize=250
+
+ # make table
+ self.table = GrDataPlotterValueTable(uid, self, 0, 0, 400, 200)
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
+ self.table.treeWidget.setSizePolicy(sizePolicy)
+ self.table.treeWidget.setEditTriggers(QtGui.QAbstractItemView.EditKeyPressed)
+ self.table.treeWidget.setSortingEnabled(True)
+ self.table.treeWidget.setDragEnabled(True)
+
+ # add things to layouts
+ self.horizontalLayout.addWidget(self.table.treeWidget)
+
+ # set up timer
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.updateRate = updateRate;
+ self.timer.start(self.updateRate)
+
+ # set up context menu ..
+ self.table.treeWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ self.table.treeWidget.customContextMenuRequested.connect(self.openMenu)
+
+ # Set up double-click to launch default plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem*, int)'),
+ self.parent.newSub);
+
+ # Allow drag/drop event from table item to plotter
+ self.connect(self.table.treeWidget,
+ QtCore.SIGNAL('itemPressed(QTreeWidgetItem*, int)'),
+ self.parent.startDrag)
+
+ def openMenu(self, pos):
+ index = self.table.treeWidget.selectedIndexes()
+ item = self.table.treeWidget.itemFromIndex(index[0])
+ itemname = str(item.text(0))
+ self.parent.propertiesMenu(itemname, self.radioclient, self.uid)
+
+
+def get_minmax(p):
+ pmin = p.min.value
+ pmax = p.max.value
+
+ # Find min/max or real or imag for GNURadio::complex
+ # TODO: fix complex
+ if(type(pmin) == ControlPort.complex):
+ pmin = min(pmin.re, pmin.im)
+ if(type(pmax) == ControlPort.complex):
+ pmax = max(pmax.re, pmax.im)
+
+ # If it's a byte stream, Python thinks it's a string.
+ try:
+ if(type(pmin) == str):
+ pmin = struct.unpack('b', pmin)[0]
+ if(type(pmax) == str):
+ pmax = struct.unpack('b', pmax)[0]
+ except struct.error:
+ pmin = []
+ pmax = []
+
+ if pmin == []:
+ pmin = None
+ else:
+ pmin = 1.1*float(pmin)
+ if pmax == []:
+ pmax = None
+ else:
+ pmax = 1.1*float(pmax)
+
+ return pmin, pmax
+
+class MyApp(object):
+ def __init__(self, args):
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ GNURadioControlPortClient(args, 'thrift', self.run, QtGui.QApplication(sys.argv).exec_)
+
+ def run(self, client):
+ MAINWindow(client).show()
+
+MyApp(sys.argv)
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx
new file mode 100644
index 0000000000..cebc00dcf4
--- /dev/null
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx
@@ -0,0 +1,875 @@
+#!/usr/bin/env python
+#
+# Copyright 2012-2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import random,math,operator
+import networkx as nx
+import matplotlib
+matplotlib.use("QT4Agg")
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
+from matplotlib.backends.backend_qt4agg import NavigationToolbar2QTAgg as NavigationToolbar
+from matplotlib.figure import Figure
+
+from PyQt4 import QtCore,Qt,Qwt5
+import PyQt4.QtGui as QtGui
+import sys, time, re, pprint
+import itertools
+
+from gnuradio import gr, ctrlport
+from gnuradio.ctrlport.GrDataPlotter import *
+
+class MAINWindow(QtGui.QMainWindow):
+ def minimumSizeHint(self):
+ return QtGui.QSize(800,600)
+
+ def __init__(self, radioclient):
+
+ super(MAINWindow, self).__init__()
+ self.radioclient = radioclient
+ self.conns = []
+ self.plots = []
+ self.knobprops = []
+
+ self.mdiArea = QtGui.QMdiArea()
+ self.mdiArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.mdiArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
+ self.setCentralWidget(self.mdiArea)
+
+ self.mdiArea.subWindowActivated.connect(self.updateMenus)
+ self.windowMapper = QtCore.QSignalMapper(self)
+ self.windowMapper.mapped[QtGui.QWidget].connect(self.setActiveSubWindow)
+
+ self.createActions()
+ self.createMenus()
+ self.createToolBars()
+ self.createStatusBar()
+ self.updateMenus()
+
+ self.setWindowTitle("GNU Radio Performance Monitor")
+ self.setUnifiedTitleAndToolBarOnMac(True)
+
+ self.newCon(radioclient)
+
+ icon = QtGui.QIcon(ctrlport.__path__[0] + "/icon.png" )
+ self.setWindowIcon(icon)
+
+ def newSubWindow(self, window, title):
+ child = window;
+ child.setWindowTitle(title)
+ self.mdiArea.addSubWindow(child)
+ self.conns.append(child)
+ child.show();
+ self.mdiArea.currentSubWindow().showMaximized()
+
+ def newCon(self, csomeBool):
+ child = MForm(self.radioclient, len(self.conns), self, dialogprompt = not csomeBool)
+ if(child.radioclient is not None):
+ child.setWindowTitle(str(child.radioclient))
+ self.mdiArea.addSubWindow(child)
+ self.mdiArea.currentSubWindow().showMaximized()
+
+ self.conns.append(child)
+ self.plots.append([])
+
+ def update(self, knobs, uid):
+ #sys.stderr.write("KNOB KEYS: {0}\n".format(knobs.keys()))
+ for plot in self.plots[uid]:
+ data = knobs[plot.name()].value
+ plot.update(data)
+ plot.stop()
+ plot.wait()
+ plot.start()
+
+ def setActiveSubWindow(self, window):
+ if window:
+ self.mdiArea.setActiveSubWindow(window)
+
+
+ def createActions(self):
+ self.newConAct = QtGui.QAction("&New Connection",
+ self, shortcut=QtGui.QKeySequence.New,
+ statusTip="Create a new file", triggered=self.newCon)
+
+ self.exitAct = QtGui.QAction("E&xit", self, shortcut="Ctrl+Q",
+ statusTip="Exit the application",
+ triggered=QtGui.qApp.closeAllWindows)
+
+ self.closeAct = QtGui.QAction("Cl&ose", self, shortcut="Ctrl+F4",
+ statusTip="Close the active window",
+ triggered=self.mdiArea.closeActiveSubWindow)
+
+ self.closeAllAct = QtGui.QAction("Close &All", self,
+ statusTip="Close all the windows",
+ triggered=self.mdiArea.closeAllSubWindows)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T);
+ self.tileAct = QtGui.QAction("&Tile", self,
+ statusTip="Tile the windows",
+ triggered=self.mdiArea.tileSubWindows,
+ shortcut=qks)
+
+ qks = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C);
+ self.cascadeAct = QtGui.QAction("&Cascade", self,
+ statusTip="Cascade the windows", shortcut=qks,
+ triggered=self.mdiArea.cascadeSubWindows)
+
+ self.nextAct = QtGui.QAction("Ne&xt", self,
+ shortcut=QtGui.QKeySequence.NextChild,
+ statusTip="Move the focus to the next window",
+ triggered=self.mdiArea.activateNextSubWindow)
+
+ self.previousAct = QtGui.QAction("Pre&vious", self,
+ shortcut=QtGui.QKeySequence.PreviousChild,
+ statusTip="Move the focus to the previous window",
+ triggered=self.mdiArea.activatePreviousSubWindow)
+
+ self.separatorAct = QtGui.QAction(self)
+ self.separatorAct.setSeparator(True)
+
+ self.aboutAct = QtGui.QAction("&About", self,
+ statusTip="Show the application's About box",
+ triggered=self.about)
+
+ self.aboutQtAct = QtGui.QAction("About &Qt", self,
+ statusTip="Show the Qt library's About box",
+ triggered=QtGui.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.newConAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.windowMenu = self.menuBar().addMenu("&Window")
+ self.updateWindowMenu()
+ self.windowMenu.aboutToShow.connect(self.updateWindowMenu)
+
+ self.menuBar().addSeparator()
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def createToolBars(self):
+ self.fileToolBar = self.addToolBar("File")
+ self.fileToolBar.addAction(self.newConAct)
+
+ self.fileToolBar = self.addToolBar("Window")
+ self.fileToolBar.addAction(self.tileAct)
+ self.fileToolBar.addAction(self.cascadeAct)
+
+ def createStatusBar(self):
+ self.statusBar().showMessage("Ready")
+
+
+ def activeMdiChild(self):
+ activeSubWindow = self.mdiArea.activeSubWindow()
+ if activeSubWindow:
+ return activeSubWindow.widget()
+ return None
+
+ def updateMenus(self):
+ hasMdiChild = (self.activeMdiChild() is not None)
+ self.closeAct.setEnabled(hasMdiChild)
+ self.closeAllAct.setEnabled(hasMdiChild)
+ self.tileAct.setEnabled(hasMdiChild)
+ self.cascadeAct.setEnabled(hasMdiChild)
+ self.nextAct.setEnabled(hasMdiChild)
+ self.previousAct.setEnabled(hasMdiChild)
+ self.separatorAct.setVisible(hasMdiChild)
+
+ def updateWindowMenu(self):
+ self.windowMenu.clear()
+ self.windowMenu.addAction(self.closeAct)
+ self.windowMenu.addAction(self.closeAllAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.tileAct)
+ self.windowMenu.addAction(self.cascadeAct)
+ self.windowMenu.addSeparator()
+ self.windowMenu.addAction(self.nextAct)
+ self.windowMenu.addAction(self.previousAct)
+ self.windowMenu.addAction(self.separatorAct)
+
+ def about(self):
+ about_info = \
+'''Copyright 2012 Free Software Foundation, Inc.\n
+This program is part of GNU Radio.\n
+GNU Radio is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.\n
+GNU Radio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n
+You should have received a copy of the GNU General Public License along with GNU Radio; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.'''
+
+ QtGui.QMessageBox.about(None, "gr-perf-monitorx", about_info)
+
+
+class ConInfoDialog(QtGui.QDialog):
+ def __init__(self, parent=None):
+ super(ConInfoDialog, self).__init__(parent)
+
+ self.gridLayout = QtGui.QGridLayout(self)
+
+
+ self.host = QtGui.QLineEdit(self);
+ self.port = QtGui.QLineEdit(self);
+ self.host.setText("localhost");
+ self.port.setText("43243");
+
+ self.buttonBox = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok |
+ QtGui.QDialogButtonBox.Cancel)
+
+ self.gridLayout.addWidget(self.host);
+ self.gridLayout.addWidget(self.port);
+ self.gridLayout.addWidget(self.buttonBox);
+
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+
+ def accept(self):
+ self.done(1);
+
+ def reject(self):
+ self.done(0);
+
+
+class DataTable(QtGui.QWidget):
+ def update(self):
+ print "update"
+
+ def closeEvent(self, event):
+ self.timer = None
+
+ def __init__(self, radioclient, G):
+ QtGui.QWidget.__init__( self)
+
+ self.layout = QtGui.QVBoxLayout(self)
+ self.hlayout = QtGui.QHBoxLayout()
+ self.layout.addLayout(self.hlayout)
+
+ self.G = G
+ self.radioclient = radioclient
+
+ self._keymap = None
+
+ self.disp = None
+
+ # Create a combobox to set the type of statistic we want.
+ self._statistic = "Instantaneous"
+ self._statistics_table = {"Instantaneous": "",
+ "Average": "avg ",
+ "Variance": "var "}
+ self.stattype = QtGui.QComboBox()
+ self.stattype.addItem("Instantaneous")
+ self.stattype.addItem("Average")
+ self.stattype.addItem("Variance")
+ self.stattype.setMaximumWidth(200)
+ self.hlayout.addWidget(self.stattype)
+ self.stattype.currentIndexChanged.connect(self.stat_changed)
+
+ # Create a checkbox to toggle sorting of graphs
+ self._sort = False
+ self.checksort = QtGui.QCheckBox("Sort")
+ self.checksort.setCheckState(self._sort)
+ self.hlayout.addWidget(self.checksort);
+ self.checksort.stateChanged.connect(self.checksort_changed)
+
+ # set up table
+ self.perfTable = Qt.QTableWidget()
+ self.perfTable.setColumnCount(2)
+ self.perfTable.verticalHeader().hide()
+ self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Runtime"] )
+ self.perfTable.horizontalHeader().setStretchLastSection(True)
+ self.perfTable.setSortingEnabled(True)
+ nodes = self.G.nodes(data=True)
+
+ # set up plot
+ self.f = plt.figure(figsize=(10,8), dpi=90)
+ self.sp = self.f.add_subplot(111)
+ self.sp.autoscale_view(True,True,True)
+ self.sp.set_autoscale_on(True)
+ self.canvas = FigureCanvas(self.f)
+
+ # set up tabs
+ self.tabber = QtGui.QTabWidget();
+ self.layout.addWidget(self.tabber);
+ self.tabber.addTab(self.perfTable,"Table View");
+ self.tabber.addTab(self.canvas, "Graph View");
+
+ # set up timer
+ self.timer = QtCore.QTimer()
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.timer.start(500)
+
+ for i in range(0,len(nodes)):
+ self.perfTable.setItem(
+ i,0,
+ Qt.QTableWidgetItem(nodes[i][0]))
+
+ def table_update(self,data):
+ for k in data.keys():
+ weight = data[k]
+ existing = self.perfTable.findItems(str(k),QtCore.Qt.MatchFixedString)
+ if(len(existing) == 0):
+ i = self.perfTable.rowCount();
+ self.perfTable.setRowCount( i+1)
+ self.perfTable.setItem( i,0, Qt.QTableWidgetItem(str(k)))
+ self.perfTable.setItem( i,1, Qt.QTableWidgetItem(str(weight)))
+ else:
+ self.perfTable.setItem( self.perfTable.row(existing[0]),1, Qt.QTableWidgetItem(str(weight)))
+
+ def stat_changed(self, index):
+ self._statistic = str(self.stattype.currentText())
+
+ def checksort_changed(self, state):
+ self._sort = state > 0
+
+class DataTableBuffers(DataTable):
+ def __init__(self, radioclient, G):
+ super(DataTableBuffers, self).__init__(radioclient, G)
+ self.perfTable.setHorizontalHeaderLabels( ["Block Name", "Percent Buffer Full"] )
+
+ def update(self):
+ nodes = self.G.nodes();
+
+ # get buffer fullness for all blocks
+ kl = map(lambda x: "%s::%soutput %% full" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes);
+ buf_knobs = self.radioclient.getKnobs(kl)
+
+ # strip values out of ctrlport response
+ buffer_fullness = dict(zip(
+ map(lambda x: x.split("::")[0], buf_knobs.keys()),
+ map(lambda x: x.value, buf_knobs.values())))
+
+ blockport_fullness = {}
+ for blk in buffer_fullness:
+ bdata = buffer_fullness[blk]
+ if bdata:
+ for port in range(0,len(bdata)):
+ blockport_fullness["%s:%d"%(blk,port)] = bdata[port]
+
+ if(self.perfTable.isVisible()):
+ self.table_update(blockport_fullness);
+
+ else:
+ if(self._sort):
+ sorted_fullness = sorted(blockport_fullness.iteritems(),
+ key=operator.itemgetter(1))
+ self._keymap = map(operator.itemgetter(0), sorted_fullness)
+ else:
+ if self._keymap:
+ sorted_fullness = len(self._keymap)*['',]
+ for b in blockport_fullness:
+ sorted_fullness[self._keymap.index(b)] = (b, blockport_fullness[b])
+ else:
+ sorted_fullness = blockport_fullness.items()
+
+ if(not self.disp):
+ self.disp = self.sp.bar(range(0,len(sorted_fullness)),
+ map(lambda x: x[1], sorted_fullness),
+ alpha=0.5)
+ self.sp.set_ylabel("% Buffers Full");
+ self.sp.set_xticks( map(lambda x: x+0.5, range(0,len(sorted_fullness))))
+ self.sp.set_xticklabels(map(lambda x: " " + x, map(lambda x: x[0], sorted_fullness)),
+ rotation="vertical", verticalalignment="bottom")
+ else:
+ self.sp.set_xticklabels(map(lambda x: " " + x, map(lambda x: x[0], sorted_fullness)),
+ rotation="vertical", verticalalignment="bottom")
+ for r,w in zip(self.disp, sorted_fullness):
+ r.set_height(w[1])
+
+ self.canvas.draw()
+
+class DataTableRuntimes(DataTable):
+ def __init__(self, radioclient, G):
+ super(DataTableRuntimes, self).__init__( radioclient, G)
+
+ def update(self):
+ nodes = self.G.nodes();
+
+ # get work time for all blocks
+ kl = map(lambda x: "%s::%swork time" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes);
+ wrk_knobs = self.radioclient.getKnobs(kl)
+
+ # strip values out of ctrlport response
+ total_work = sum(map(lambda x: x.value, wrk_knobs.values()))
+ if(total_work == 0):
+ total_work = 1
+ work_times = dict(zip(
+ map(lambda x: x.split("::")[0], wrk_knobs.keys()),
+ map(lambda x: x.value/total_work, wrk_knobs.values())))
+
+ # update table view
+ if(self.perfTable.isVisible()):
+ self.table_update(work_times)
+
+ else:
+ if(self._sort):
+ sorted_work = sorted(work_times.iteritems(), key=operator.itemgetter(1))
+ self._keymap = map(operator.itemgetter(0), sorted_work)
+ else:
+ if self._keymap:
+ sorted_work = len(self._keymap)*['',]
+ for b in work_times:
+ sorted_work[self._keymap.index(b)] = (b, work_times[b])
+ else:
+ sorted_work = work_times.items()
+
+ f = plt.figure(self.f.number)
+ if(not self.disp):
+ self.disp = self.sp.bar(range(0,len(sorted_work)),
+ map(lambda x: x[1], sorted_work),
+ alpha=0.5)
+ self.sp.set_ylabel("% Runtime");
+ self.sp.set_xticks( map(lambda x: x+0.5, range(0,len(sorted_work))))
+ self.sp.set_xticklabels( map(lambda x: " " + x[0], sorted_work),
+ rotation="vertical", verticalalignment="bottom" )
+ else:
+ self.sp.set_xticklabels( map(lambda x: " " + x[0], sorted_work),
+ rotation="vertical", verticalalignment="bottom" )
+ for r,w in zip(self.disp, sorted_work):
+ r.set_height(w[1])
+
+ self.canvas.draw()
+
+class MForm(QtGui.QWidget):
+ def update(self):
+ try:
+ try:
+ # update current clock type
+ self.prevent_clock_change = True;
+ kl1 = None;
+ if(self.clockKey == None):
+ kl1 = self.radioclient.getRe([".*perfcounter_clock"])
+ else:
+ kl1 = self.radioclient.getKnobs([self.clockKey])
+ self.clockKey = kl1.keys()[0]
+ self.currClock = kl1[self.clockKey].value
+ self.clockSelIdx = self.clocks.values().index(self.currClock)
+ self.clockSel.setCurrentIndex(self.clockSelIdx)
+ self.prevent_clock_change = False
+ except:
+ print "WARNING: Failed to get current clock setting!"
+
+ nodes_stream = self.G_stream.nodes()
+ nodes_msg = self.G_msg.nodes()
+
+ # get current buffer depths of all output buffers
+ kl = map(lambda x: "%s::%soutput %% full" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes_stream);
+
+ st = time.time()
+ buf_knobs = self.radioclient.getKnobs(kl)
+ td1 = time.time() - st;
+
+ # strip values out of ctrlport response
+ buf_vals = dict(zip(
+ map(lambda x: x.split("::")[0], buf_knobs.keys()),
+ map(lambda x: x.value, buf_knobs.values())))
+
+ # get work time for all blocks
+ kl = map(lambda x: "%s::%swork time" % \
+ (x, self._statistics_table[self._statistic]),
+ nodes_stream);
+ st = time.time()
+ wrk_knobs = self.radioclient.getKnobs(kl)
+ td2 = time.time() - st;
+
+ # strip values out of ctrlport response
+ total_work = sum(map(lambda x: x.value, wrk_knobs.values()))
+ if(total_work == 0):
+ total_work = 1
+ work_times = dict(zip(
+ map(lambda x: x.split("::")[0], wrk_knobs.keys()),
+ map(lambda x: x.value/total_work, wrk_knobs.values())))
+ work_times_padded = dict(zip(
+ self.G.nodes(),
+ [0.1]*len(self.G.nodes())))
+ work_times_padded.update(work_times)
+
+ for n in nodes_stream:
+ # ne is the list of edges away from this node!
+ ne = self.G.edges([n],True);
+ #for e in ne: # iterate over edges from this block
+ for e in ne: # iterate over edges from this block
+ # get the right output buffer/port weight for each edge
+ sourceport = e[2]["sourceport"];
+ if(e[2]["type"] == "stream"):
+ newweight = buf_vals[n][sourceport]
+ e[2]["weight"] = newweight;
+
+ for n in nodes_msg:
+ ne = self.G.edges([n],True);
+ for e in ne: # iterate over edges from this block
+ sourceport = e[2]["sourceport"];
+ if(e[2]["type"] == "msg"):
+ newweight = 0.01;
+ e[2]["weight"] = newweight;
+
+ # set updated weights
+ #self.node_weights = map(lambda x: 20+2000*work_times[x], nodes_stream);
+ self.node_weights = map(lambda x: 20+2000*work_times_padded[x], self.G.nodes());
+ self.edge_weights = map(lambda x: 100.0*x[2]["weight"], self.G.edges(data=True));
+
+ # draw graph updates
+ self.updateGraph();
+
+ latency = td1 + td2;
+ self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\
+ (latency*1000))
+
+ except Exception, e:
+ sys.stderr.write("gr-perf-monitorx: radio.getKnobs threw exception ({0}).\n".format(e))
+ if(type(self.parent) is MAINWindow):
+ # Find window of connection
+ remove = []
+ for p in self.parent.mdiArea.subWindowList():
+ if self.parent.conns[self.uid] == p.widget():
+ remove.append(p)
+
+ # Remove subwindows for connection and plots
+ for r in remove:
+ self.parent.mdiArea.removeSubWindow(r)
+
+ # Clean up self
+ self.close()
+ else:
+ sys.exit(1)
+ return
+
+ def rtt(self):
+ self.parent.newSubWindow( DataTableRuntimes(self.radioclient, self.G_stream), "Runtime Table" );
+
+ def bpt(self):
+ self.parent.newSubWindow( DataTableBuffers(self.radioclient, self.G_stream), "Buffers Table" );
+
+ def resetPCs(self):
+ knobs = []
+ for b in self.blocks_list:
+ knobs += [self.radioclient.Knob(b + "::reset_perf_counters"),]
+ k = self.radioclient.setKnobs(knobs)
+
+ def toggleFlowgraph(self):
+ if self.pauseFGAct.isChecked():
+ self.pauseFlowgraph()
+ else:
+ self.unpauseFlowgraph()
+
+ def pauseFlowgraph(self):
+ knobs = [self.radioclient.Knob(self.top_block + "::lock"),
+ self.radioclient.Knob(self.top_block + "::stop")]
+ k = self.radioclient.setKnobs(knobs)
+
+ def unpauseFlowgraph(self):
+ knobs = [self.radioclient.Knob(self.top_block + "::unlock")]
+ k = self.radioclient.setKnobs(knobs)
+
+ def stat_changed(self, index):
+ self._statistic = str(self.stattype.currentText())
+
+ def update_clock(self, clkidx):
+ if(self.prevent_clock_change):
+ return;
+ idx = self.clockSel.currentIndex();
+ clk = self.clocks.values()[idx]
+# print "UPDATE CLOCK!!! %d -> %d"%(idx,clk);
+ k = self.radioclient.getKnobs([self.clockKey]);
+ k[self.clockKey].value = clk;
+ km = {};
+ km[self.clockKey] = k[self.clockKey];
+ self.radioclient.setKnobs(km);
+
+ def __init__(self, radioclient, uid=0, parent=None, dialogprompt = False):
+
+ super(MForm, self).__init__()
+ self.radioclient = radioclient
+# print("before radioclient.getHost()", radioclient.getHost(), radioclient.getPort(), "prompt", prompt)
+ if(dialogprompt or radioclient.getHost() is None or radioclient.getPort() is None):
+# print("before ConInfoDialog")
+ askinfo = ConInfoDialog(self);
+ if askinfo.exec_():
+ host = str(askinfo.host.text());
+ port = str(askinfo.port.text());
+# print("before radioclient.newConnection host: %s port: %s"%(host,port))
+ newradio = self.radioclient.newConnection(host, port)
+ if newradio is None:
+ print("Error making a %s connection to %s:%s from %s" % (radioclient.getName(), host, port, radioclient))
+ else:
+ self.radioclient = newradio
+
+ else:
+ self.radioclient = None
+ return
+
+ self.uid = uid
+ self.parent = parent
+
+ self.layoutTop = QtGui.QVBoxLayout(self)
+ self.ctlBox = QtGui.QHBoxLayout();
+ self.layout = QtGui.QHBoxLayout()
+
+ self.layoutTop.addLayout(self.ctlBox);
+ self.layoutTop.addLayout(self.layout);
+
+ self.rttAct = QtGui.QAction("Runtime Table",
+ self, statusTip="Runtime Table", triggered=self.rtt)
+ self.rttBut = Qt.QToolButton()
+ self.rttBut.setDefaultAction(self.rttAct);
+ self.ctlBox.addWidget(self.rttBut);
+
+ self.bptAct = QtGui.QAction("Buffer Table",
+ self, statusTip="Buffer Table", triggered=self.bpt)
+ self.bptBut = Qt.QToolButton()
+ self.bptBut.setDefaultAction(self.bptAct);
+ self.ctlBox.addWidget(self.bptBut);
+
+ self.resetPCsAct = QtGui.QAction("Reset", self,
+ statusTip="Reset all Performance Counters",
+ triggered=self.resetPCs)
+ self.resetPCsBut = Qt.QToolButton()
+ self.resetPCsBut.setDefaultAction(self.resetPCsAct);
+ self.ctlBox.addWidget(self.resetPCsBut);
+
+ self.pauseFGAct = QtGui.QAction("Pause", self,
+ statusTip="Pause the Flowgraph",
+ triggered=self.toggleFlowgraph)
+ self.pauseFGAct.setCheckable(True)
+ self.pauseFGBut = Qt.QToolButton()
+ self.pauseFGBut.setDefaultAction(self.pauseFGAct);
+ self.ctlBox.addWidget(self.pauseFGBut);
+
+ self.prevent_clock_change = True;
+ self.clockKey = None;
+ self.clocks = {"MONOTONIC":1, "THREAD":3};
+ self.clockSel = QtGui.QComboBox(self);
+ map(lambda x: self.clockSel.addItem(x), self.clocks.keys());
+ self.ctlBox.addWidget(self.clockSel);
+ self.clockSel.currentIndexChanged.connect(self.update_clock);
+ self.prevent_clock_change = False;
+
+ self._statistic = "Instantaneous"
+ self._statistics_table = {"Instantaneous": "",
+ "Average": "avg ",
+ "Variance": "var "}
+ self.stattype = QtGui.QComboBox()
+ self.stattype.addItem("Instantaneous")
+ self.stattype.addItem("Average")
+ self.stattype.addItem("Variance")
+ self.stattype.setMaximumWidth(200)
+ self.ctlBox.addWidget(self.stattype);
+ self.stattype.currentIndexChanged.connect(self.stat_changed)
+
+# self.setLayout(self.layout);
+
+ self.radio = radioclient
+ self.knobprops = self.radio.properties([])
+ self.parent.knobprops.append(self.knobprops)
+
+ self.timer = QtCore.QTimer()
+ self.constupdatediv = 0
+ self.tableupdatediv = 0
+ plotsize=250
+
+
+ # Set up the graph of blocks
+ input_name = lambda x: x+"::avg input % full"
+ output_name = lambda x: x+"::avg output % full"
+ wtime_name = lambda x: x+"::avg work time"
+ nout_name = lambda x: x+"::avg noutput_items"
+ nprod_name = lambda x: x+"::avg nproduced"
+
+ tmplist = []
+ knobs = self.radio.getKnobs([])
+ edgelist = None
+ msgedgelist = None
+ for k in knobs:
+ propname = k.split("::")
+ blockname = propname[0]
+ keyname = propname[1]
+ if(keyname == "edge list"):
+ edgelist = knobs[k].value
+ self.top_block = blockname
+ elif(keyname == "msg edges list"):
+ msgedgelist = knobs[k].value
+ elif(blockname not in tmplist):
+ # only take gr_blocks (no hier_block2)
+ if(knobs.has_key(input_name(blockname))):
+ tmplist.append(blockname)
+
+
+ if not edgelist:
+ sys.stderr.write("Could not find list of edges from flowgraph. " + \
+ "Make sure the option 'edges_list' is enabled " + \
+ "in the ControlPort configuration.\n\n")
+ sys.exit(1)
+
+ self.blocks_list = tmplist
+ edges = edgelist.split("\n")[0:-1]
+ msgedges = msgedgelist.split("\n")[0:-1]
+
+ edgepairs_stream = [];
+ edgepairs_msg = [];
+
+ # add stream connections
+ for e in edges:
+ _e = e.split("->")
+ edgepairs_stream.append( (_e[0].split(":")[0], _e[1].split(":")[0],
+ {"type":"stream", "sourceport":int(_e[0].split(":")[1])}) );
+
+ # add msg connections
+ for e in msgedges:
+ _e = e.split("->")
+ edgepairs_msg.append( (_e[0].split(":")[0], _e[1].split(":")[0],
+ {"type":"msg", "sourceport":_e[0].split(":")[1]}) );
+
+ self.G = nx.MultiDiGraph();
+ self.G_stream = nx.MultiDiGraph();
+ self.G_msg = nx.MultiDiGraph();
+
+ self.G.add_edges_from(edgepairs_stream);
+ self.G.add_edges_from(edgepairs_msg);
+
+ self.G_stream.add_edges_from(edgepairs_stream);
+ self.G_msg.add_edges_from(edgepairs_msg);
+
+ n_edges = self.G.edges(data=True);
+ for e in n_edges:
+ e[2]["weight"] = 5+random.random()*10;
+
+ self.G.clear();
+ self.G.add_edges_from(n_edges);
+
+
+ self.f = plt.figure(figsize=(10,8), dpi=90)
+ self.sp = self.f.add_subplot(111);
+ self.sp.autoscale_view(True,True,True);
+ self.sp.set_autoscale_on(True)
+
+ self.canvas = FigureCanvas(self.f)
+ self.layout.addWidget(self.canvas);
+
+ self.pos = nx.graphviz_layout(self.G);
+ #self.pos = nx.pygraphviz_layout(self.G);
+ #self.pos = nx.spectral_layout(self.G);
+ #self.pos = nx.circular_layout(self.G);
+ #self.pos = nx.shell_layout(self.G);
+ #self.pos = nx.spring_layout(self.G);
+
+ # generate weights and plot
+ self.update();
+
+ # set up timer
+ self.timer = QtCore.QTimer()
+ self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
+ self.timer.start(1000)
+
+ # Set up mouse callback functions to move blocks around.
+ self._grabbed = False
+ self._current_block = ''
+ self.f.canvas.mpl_connect('button_press_event',
+ self.button_press)
+ self.f.canvas.mpl_connect('motion_notify_event',
+ self.mouse_move)
+ self.f.canvas.mpl_connect('button_release_event',
+ self.button_release)
+
+ def button_press(self, event):
+ x, y = event.xdata, event.ydata
+ thrsh = 100
+
+ if(x is not None and y is not None):
+ nearby = map(lambda z: math.sqrt( math.pow(x-z[0],2) + math.pow(y-z[1],2)), self.pos.values())
+ i = nearby.index(min(nearby))
+ if(abs(self.pos.values()[i][0] - x) < thrsh and
+ abs(self.pos.values()[i][1]-y) < thrsh):
+ self._current_block = self.pos.keys()[i]
+ #print "MOVING BLOCK: ", self._current_block
+ #print "CUR POS: ", self.pos.values()[i]
+ self._grabbed = True
+
+ def mouse_move(self, event):
+ if self._grabbed:
+ x, y = event.xdata, event.ydata
+ if(x is not None and y is not None):
+ #print "NEW POS: ", (x,y)
+ self.pos[self._current_block] = (x,y)
+ self.updateGraph();
+
+ def button_release(self, event):
+ self._grabbed = False
+
+
+ def openMenu(self, pos):
+ index = self.table.treeWidget.selectedIndexes()
+ item = self.table.treeWidget.itemFromIndex(index[0])
+ itemname = str(item.text(0))
+ self.parent.propertiesMenu(itemname, self.radioclient, self.uid)
+
+ def updateGraph(self):
+
+ self.canvas.updateGeometry()
+ self.sp.clear();
+ plt.figure(self.f.number)
+ plt.subplot(111);
+ nx.draw(self.G, self.pos,
+ edge_color=self.edge_weights,
+ node_color='#A0CBE2',
+ width=map(lambda x: 3+math.log(x), self.edge_weights),
+ node_shape="s",
+ node_size=self.node_weights,
+ #edge_cmap=plt.cm.Blues,
+ edge_cmap=plt.cm.Reds,
+ ax=self.sp,
+ arrows=False
+ )
+ nx.draw_networkx_labels(self.G, self.pos,
+ font_size=12)
+
+ self.canvas.draw();
+ self.canvas.show();
+
+
+class MyApp(object):
+ def __init__(self, args):
+ p = gr.prefs()
+ cp_on = p.get_bool("ControlPort", "on", False)
+ cp_edges = p.get_bool("ControlPort", "edges_list", False)
+ pcs_on = p.get_bool("PerfCounters", "on", False)
+ pcs_exported = p.get_bool("PerfCounters", "export", False)
+ if(not (pcs_on and cp_on and pcs_exported and cp_edges)):
+ print("Configuration has not turned on all of the appropriate ControlPort features:")
+ print("\t[ControlPort] on = {0}".format(cp_on))
+ print("\t[ControlPort] edges_list = {0}".format(cp_edges))
+ print("\t[PerfCounters] on = {0}".format(pcs_on))
+ print("\t[PerfCounters] export = {0}".format(pcs_exported))
+ exit(1)
+
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ GNURadioControlPortClient(args, 'thrift', self.run, QtGui.QApplication(sys.argv).exec_)
+
+ def run(self, client):
+ MAINWindow(client).show()
+
+MyApp(sys.argv)
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py
index 8bb26d93a1..f651be2449 100644
--- a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py
+++ b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py
@@ -48,9 +48,9 @@ class monitor:
print "monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints())
try:
cmd = map(lambda a: [self.tool,
- re.search("\d+\.\d+\.\d+\.\d+",a).group(0),
- re.search("-p (\d+)",a).group(1)],
- gr.rpcmanager_get().endpoints())[0]
+ re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)",a).group(1),
+ re.search("-p (\d+)",a).group(1)],
+ gr.rpcmanager_get().endpoints())[0]
print "running: %s"%(str(cmd))
self.proc = subprocess.Popen(cmd);
self.started = True
diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
index 1a08ac5ae6..55b62a12ac 100755
--- a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
+++ b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py
@@ -76,6 +76,38 @@ class test_tag_utils (gr_unittest.TestCase):
self.assertTrue(pmt.equal(t_tuple.value, value))
self.assertEqual(t_tuple.offset, offset)
+ def test_003(self):
+ offsets = (6, 3, 8)
+ key = pmt.string_to_symbol('key')
+ srcid = pmt.string_to_symbol('qa_tag_utils')
+ tags = []
+
+ for k in offsets:
+ t = gr.tag_t()
+ t.offset = k
+ t.key = key
+ t.value = pmt.from_long(k)
+ t.srcid = srcid
+ tags.append(t)
+
+ for k, t in zip(sorted(offsets),
+ sorted(tags, key=gr.tag_t_offset_compare_key())):
+ self.assertEqual(t.offset, k)
+ self.assertTrue(pmt.equal(t.key, key))
+ self.assertTrue(pmt.equal(t.value, pmt.from_long(k)))
+ self.assertTrue(pmt.equal(t.srcid, srcid))
+
+ tmin = min(tags, key=gr.tag_t_offset_compare_key())
+ self.assertEqual(tmin.offset, min(offsets))
+ self.assertTrue(pmt.equal(tmin.key, key))
+ self.assertTrue(pmt.equal(tmin.value, pmt.from_long(min(offsets))))
+ self.assertTrue(pmt.equal(tmin.srcid, srcid))
+
+ tmax = max(tags, key=gr.tag_t_offset_compare_key())
+ self.assertEqual(tmax.offset, max(offsets))
+ self.assertTrue(pmt.equal(tmax.key, key))
+ self.assertTrue(pmt.equal(tmax.value, pmt.from_long(max(offsets))))
+ self.assertTrue(pmt.equal(tmax.srcid, srcid))
if __name__ == '__main__':
diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
index dc36e05250..a7745428c7 100644
--- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
+++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py
@@ -108,3 +108,36 @@ def python_to_tag(tag_struct):
return tag
else:
return None
+
+def tag_t_offset_compare_key():
+ """
+ Convert a tag_t_offset_compare function into a key=function
+ This method is modeled after functools.cmp_to_key(_func_).
+ It can be used by functions that accept a key function, such as
+ sorted(), min(), max(), etc. to compare tags by their offsets,
+ e.g., sorted(tag_list, key=gr.tag_t_offset_compare_key()).
+ """
+ class K(object):
+ def __init__(self, obj, *args):
+ self.obj = obj
+ def __lt__(self, other):
+ # x.offset < y.offset
+ return gr.tag_t_offset_compare(self.obj, other.obj)
+ def __gt__(self, other):
+ # y.offset < x.offset
+ return gr.tag_t_offset_compare(other.obj, self.obj)
+ def __eq__(self, other):
+ # not (x.offset < y.offset) and not (y.offset < x.offset)
+ return not gr.tag_t_offset_compare(self.obj, other.obj) and \
+ not gr.tag_t_offset_compare(other.obj, self.obj)
+ def __le__(self, other):
+ # not (y.offset < x.offset)
+ return not gr.tag_t_offset_compare(other.obj, self.obj)
+ def __ge__(self, other):
+ # not (x.offset < y.offset)
+ return not gr.tag_t_offset_compare(self.obj, other.obj)
+ def __ne__(self, other):
+ # (x.offset < y.offset) or (y.offset < x.offset)
+ return gr.tag_t_offset_compare(self.obj, other.obj) or \
+ gr.tag_t_offset_compare(other.obj, self.obj)
+ return K
diff --git a/gnuradio-runtime/python/gnuradio/gr/top_block.py b/gnuradio-runtime/python/gnuradio/gr/top_block.py
index f449d98489..2efcbd9aae 100644
--- a/gnuradio-runtime/python/gnuradio/gr/top_block.py
+++ b/gnuradio-runtime/python/gnuradio/gr/top_block.py
@@ -63,11 +63,13 @@ class _top_block_waiter(_threading.Thread):
top_block_wait_unlocked(self.tb)
self.event.set()
- def wait(self):
+ def wait(self, handle_sigint=True):
try:
- while not self.event.isSet():
- self.event.wait(0.100)
+ while not self.event.wait(0.1):
+ pass
except KeyboardInterrupt:
+ if not handle_sigint:
+ raise
self.tb.stop()
self.wait()
@@ -98,6 +100,7 @@ class top_block(hier_block2):
"""
# not calling hier_block2.__init__, we set our own _impl
self._impl = top_block_swig(name)
+ self.handle_sigint = True
def start(self, max_noutput_items=10000000):
"""
@@ -128,7 +131,7 @@ class top_block(hier_block2):
"""
Wait for the flowgraph to finish running
"""
- _top_block_waiter(self._impl).wait()
+ _top_block_waiter(self._impl).wait(self.handle_sigint)
def dot_graph(self):
"""
diff --git a/gnuradio-runtime/swig/gr_types.i b/gnuradio-runtime/swig/gr_types.i
index 8ae953b904..e329a4ce9f 100644
--- a/gnuradio-runtime/swig/gr_types.i
+++ b/gnuradio-runtime/swig/gr_types.i
@@ -80,15 +80,19 @@ namespace std {
%template(gr_vector_vector_complexf) std::vector< std::vector< std::complex<float> > >;
%template(gr_vector_vector_complexd) std::vector< std::vector< std::complex<double> > >;
-// Fix for Issue #529
-#ifdef SIZE_T_32
- // On 32-bit systems, whenever we see std::vector<size_t>, replace it
- // with vector<unsigned int>
+// Fix for Issue #529: replace std::vector<size_t> with its equivalent
+// in element size, one of "unsigned int", "unsigned long", or
+// "unsigned long long". The replacement depends on the sizeof each
+// type, as determined in GrSwig.cmake GR_SWIG_MAKE. For SWIG >=
+// 3.0.0, none of these will be defined because this issue seems to
+// have been fixed.
+
+#if defined(SIZE_T_UINT)
%apply std::vector<unsigned int> { std::vector<size_t> };
-#else
- // On 64-bit systems, whenever we see std::vector<size_t>, replace it
- // with vector<long unsigned int>
- %apply std::vector<long unsigned int> { std::vector<size_t> };
+#elif defined(SIZE_T_UL)
+ %apply std::vector<unsigned long> { std::vector<size_t> };
+#elif defined(SIZE_T_ULL)
+ %apply std::vector<unsigned long long> { std::vector<size_t> };
#endif
#endif /* SWIG_GR_TYPES_I */
diff --git a/gnuradio-runtime/swig/prefs.i b/gnuradio-runtime/swig/prefs.i
index ac5fab7adc..4774146b69 100644
--- a/gnuradio-runtime/swig/prefs.i
+++ b/gnuradio-runtime/swig/prefs.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006,2013 Free Software Foundation, Inc.
+ * Copyright 2006,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,6 +25,8 @@ class gr::prefs
public:
static gr::prefs *singleton();
+ void add_config_file(const std::string &configfile);
+
virtual ~prefs();
std::string to_string();
diff --git a/gr-analog/examples/CMakeLists.txt b/gr-analog/examples/CMakeLists.txt
index f0f55b50c8..acb0656b7f 100644
--- a/gr-analog/examples/CMakeLists.txt
+++ b/gr-analog/examples/CMakeLists.txt
@@ -25,3 +25,10 @@ GR_PYTHON_INSTALL(PROGRAMS
DESTINATION ${GR_PKG_ANALOG_EXAMPLES_DIR}
COMPONENT "analog_python"
)
+
+install(
+ FILES
+ noise_power.grc
+ DESTINATION ${GR_PKG_ANALOG_EXAMPLES_DIR}
+ COMPONENT "analog_python"
+)
diff --git a/gr-analog/examples/noise_power.grc b/gr-analog/examples/noise_power.grc
new file mode 100644
index 0000000000..10a8c62aad
--- /dev/null
+++ b/gr-analog/examples/noise_power.grc
@@ -0,0 +1,1675 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.7'?>
+<flow_graph>
+ <timestamp>Sun May 10 20:26:24 2015</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>noise_power</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(176, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_fastnoise_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_fastnoise_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>noise_type</key>
+ <value>analog.GR_GAUSSIAN</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>samples</key>
+ <value>8192</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 75)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_noise_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_noise_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>noise_type</key>
+ <value>analog.GR_GAUSSIAN</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 267)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(208, 99)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(208, 283)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_complex_to_mag_squared</key>
+ <param>
+ <key>id</key>
+ <value>blocks_complex_to_mag_squared_2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(368, 104)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_complex_to_mag_squared</key>
+ <param>
+ <key>id</key>
+ <value>blocks_complex_to_mag_squared_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(368, 288)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_fastnoise_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_fastnoise_source_x_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>noise_type</key>
+ <value>analog.GR_GAUSSIAN</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>samples</key>
+ <value>8192</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 171)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_noise_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_noise_source_x_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>noise_type</key>
+ <value>analog.GR_GAUSSIAN</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 347)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0_2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(208, 363)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(208, 195)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_abs_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_abs_xx_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(368, 200)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_multiply_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_multiply_xx_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(480, 184)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_nlog10_ff</key>
+ <param>
+ <key>id</key>
+ <value>blocks_nlog10_ff_0_2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(784, 355)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>single_pole_iir_filter_xx</key>
+ <param>
+ <key>id</key>
+ <value>single_pole_iir_filter_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>0.001</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(592, 99)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>single_pole_iir_filter_xx</key>
+ <param>
+ <key>id</key>
+ <value>single_pole_iir_filter_xx_0_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>0.001</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(592, 283)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_nlog10_ff</key>
+ <param>
+ <key>id</key>
+ <value>blocks_nlog10_ff_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(784, 91)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_nlog10_ff</key>
+ <param>
+ <key>id</key>
+ <value>blocks_nlog10_ff_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(784, 187)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_nlog10_ff</key>
+ <param>
+ <key>id</key>
+ <value>blocks_nlog10_ff_0_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(784, 275)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>single_pole_iir_filter_xx</key>
+ <param>
+ <key>id</key>
+ <value>single_pole_iir_filter_xx_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>0.001</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(592, 195)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>single_pole_iir_filter_xx</key>
+ <param>
+ <key>id</key>
+ <value>single_pole_iir_filter_xx_0_2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>0.001</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(592, 363)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_abs_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_abs_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(368, 368)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_multiply_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_multiply_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(480, 352)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_number_sink</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_number_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg</key>
+ <value>0.01</value>
+ </param>
+ <param>
+ <key>graph_type</key>
+ <value>qtgui.NUM_GRAPH_NONE</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value>Complex Fast</value>
+ </param>
+ <param>
+ <key>unit1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value>Real Fast</value>
+ </param>
+ <param>
+ <key>unit2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value>Complex Noise</value>
+ </param>
+ <param>
+ <key>unit3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value>Real Noise</value>
+ </param>
+ <param>
+ <key>unit4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>unit5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>unit6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>unit7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>unit8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>unit9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>unit10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>("black", "black")</value>
+ </param>
+ <param>
+ <key>factor10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(992, 208)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Noise Amplitude</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.1</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 435)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_1</source_block_id>
+ <sink_block_id>blocks_throttle_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_noise_source_x_0</source_block_id>
+ <sink_block_id>blocks_throttle_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_noise_source_x_1</source_block_id>
+ <sink_block_id>blocks_throttle_0_2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_complex_to_mag_squared_2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0_1</source_block_id>
+ <sink_block_id>blocks_complex_to_mag_squared_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0_2</source_block_id>
+ <sink_block_id>blocks_abs_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0_0</source_block_id>
+ <sink_block_id>blocks_abs_xx_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_abs_xx_0</source_block_id>
+ <sink_block_id>blocks_multiply_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_abs_xx_0</source_block_id>
+ <sink_block_id>blocks_multiply_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_abs_xx_0_0</source_block_id>
+ <sink_block_id>blocks_multiply_xx_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_abs_xx_0_0</source_block_id>
+ <sink_block_id>blocks_multiply_xx_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>single_pole_iir_filter_xx_0</source_block_id>
+ <sink_block_id>blocks_nlog10_ff_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>single_pole_iir_filter_xx_0_0</source_block_id>
+ <sink_block_id>blocks_nlog10_ff_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>single_pole_iir_filter_xx_0_1</source_block_id>
+ <sink_block_id>blocks_nlog10_ff_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>single_pole_iir_filter_xx_0_2</source_block_id>
+ <sink_block_id>blocks_nlog10_ff_0_2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_nlog10_ff_0</source_block_id>
+ <sink_block_id>qtgui_number_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_nlog10_ff_0_0</source_block_id>
+ <sink_block_id>qtgui_number_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_nlog10_ff_0_1</source_block_id>
+ <sink_block_id>qtgui_number_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>2</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_nlog10_ff_0_2</source_block_id>
+ <sink_block_id>qtgui_number_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>3</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_multiply_xx_0_0</source_block_id>
+ <sink_block_id>single_pole_iir_filter_xx_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_multiply_xx_0</source_block_id>
+ <sink_block_id>single_pole_iir_filter_xx_0_2</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_complex_to_mag_squared_1</source_block_id>
+ <sink_block_id>single_pole_iir_filter_xx_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_complex_to_mag_squared_2</source_block_id>
+ <sink_block_id>single_pole_iir_filter_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-analog/grc/analog_pwr_squelch_xx.xml b/gr-analog/grc/analog_pwr_squelch_xx.xml
index 32d9c0e947..a75f85cf10 100644
--- a/gr-analog/grc/analog_pwr_squelch_xx.xml
+++ b/gr-analog/grc/analog_pwr_squelch_xx.xml
@@ -34,11 +34,13 @@
<param>
<name>Alpha</name>
<key>alpha</key>
+ <value>1e-4</value>
<type>real</type>
</param>
<param>
<name>Ramp</name>
<key>ramp</key>
+ <value>0</value>
<type>int</type>
</param>
<param>
diff --git a/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t b/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
index a6377ad7fb..850633979c 100644
--- a/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
+++ b/gr-analog/include/gnuradio/analog/fastnoise_source_X.h.t
@@ -47,10 +47,15 @@ namespace gr {
typedef boost::shared_ptr<@BASE_NAME@> sptr;
/*! \brief Make a fast noise source
- * \param type the random distribution to use (see gnuradio/analog/noise_type.h)
- * \param ampl a scaling factor for the output; for Gaussian sources, this is the std. dev.
- * \param seed seed for random generators. Note that for uniform and
- * Gaussian distributions, this should be a negative number.
+ * \param type the random distribution to use (see
+ * gnuradio/analog/noise_type.h)
+ * \param ampl the standard deviation of a 1-d noise process. If
+ * this is the complex source, this parameter is split
+ * among the real and imaginary parts:
+ * <pre>(ampl/sqrt(2))x + j(ampl/sqrt(2))y</pre>
+ * \param seed seed for random generators. Note that for uniform
+ * and Gaussian distributions, this should be a negative
+ * number.
* \param samples Number of samples to pre-generate
*/
static sptr make(noise_type_t type, float ampl,
@@ -58,7 +63,17 @@ namespace gr {
virtual @TYPE@ sample() = 0;
virtual @TYPE@ sample_unbiased() = 0;
+ /*!
+ * Set the noise type. Nominally from the
+ * gr::analog::noise_type_t selections, but only GR_GAUSSIAN and
+ * GR_UNIFORM are currently available.
+ */
virtual void set_type(noise_type_t type) = 0;
+
+ /*!
+ * Set the standard deviation (amplitude) of the 1-d noise
+ * process.
+ */
virtual void set_amplitude(float ampl) = 0;
virtual noise_type_t type() const = 0;
diff --git a/gr-analog/include/gnuradio/analog/noise_source_X.h.t b/gr-analog/include/gnuradio/analog/noise_source_X.h.t
index 31e742a4ed..f619ca5146 100644
--- a/gr-analog/include/gnuradio/analog/noise_source_X.h.t
+++ b/gr-analog/include/gnuradio/analog/noise_source_X.h.t
@@ -47,14 +47,29 @@ namespace gr {
typedef boost::shared_ptr<@BASE_NAME@> sptr;
/*! Build a noise source
- * \param type the random distribution to use (see gnuradio/analog/noise_type.h)
- * \param ampl a scaling factor for the output; for Gaussian sources, this is the std. dev.
- * \param seed seed for random generators. Note that for uniform and
- * Gaussian distributions, this should be a negative number.
+ * \param type the random distribution to use (see
+ * gnuradio/analog/noise_type.h)
+ * \param ampl the standard deviation of a 1-d noise process. If
+ * this is the complex source, this parameter is split
+ * among the real and imaginary parts:
+ * <pre>(ampl/sqrt(2))x + j(ampl/sqrt(2))y</pre>
+ * \param seed seed for random generators. Note that for uniform
+ * and Gaussian distributions, this should be a negative
+ * number.
*/
static sptr make(noise_type_t type, float ampl, long seed=0);
+ /*!
+ * Set the noise type. Nominally from the
+ * gr::analog::noise_type_t selections, but only GR_GAUSSIAN and
+ * GR_UNIFORM are currently available.
+ */
virtual void set_type(noise_type_t type) = 0;
+
+ /*!
+ * Set the standard deviation (amplitude) of the 1-d noise
+ * process.
+ */
virtual void set_amplitude(float ampl) = 0;
virtual noise_type_t type() const = 0;
diff --git a/gr-analog/include/gnuradio/analog/pwr_squelch_cc.h b/gr-analog/include/gnuradio/analog/pwr_squelch_cc.h
index 6913d62934..324743d965 100644
--- a/gr-analog/include/gnuradio/analog/pwr_squelch_cc.h
+++ b/gr-analog/include/gnuradio/analog/pwr_squelch_cc.h
@@ -49,10 +49,14 @@ namespace gr {
* \brief Make power-based squelch block.
*
* \param db threshold (in dB) for power squelch
- * \param alpha Gain of averaging filter
- * \param ramp sets response characteristic.
+ * \param alpha Gain of averaging filter. Defaults to 0.0001.
+ * \param ramp sets response characteristic. Defaults to 0.
* \param gate if true, no output if no squelch tone.
- * if false, output 0's if no squelch tone.
+ * if false, output 0's if no squelch tone (default).
+ *
+ * The block will emit a tag with the key pmt::intern("squelch_sob")
+ * with the value of pmt::PMT_NIL on the first item it passes, and with
+ * the key pmt::intern("squelch:eob") on the last item it passes.
*/
static sptr make(double db, double alpha=0.0001,
int ramp=0, bool gate=false);
diff --git a/gr-analog/include/gnuradio/analog/pwr_squelch_ff.h b/gr-analog/include/gnuradio/analog/pwr_squelch_ff.h
index 46046eae07..a65cedaa57 100644
--- a/gr-analog/include/gnuradio/analog/pwr_squelch_ff.h
+++ b/gr-analog/include/gnuradio/analog/pwr_squelch_ff.h
@@ -49,10 +49,14 @@ namespace gr {
* \brief Make power-based squelch block.
*
* \param db threshold (in dB) for power squelch
- * \param alpha Gain of averaging filter
- * \param ramp sets response characteristic.
+ * \param alpha Gain of averaging filter. Defaults to 0.0001.
+ * \param ramp sets response characteristic. Defaults to 0.
* \param gate if true, no output if no squelch tone.
- * if false, output 0's if no squelch tone.
+ * if false, output 0's if no squelch tone (default).
+ *
+ * The block will emit a tag with the key pmt::intern("squelch_sob")
+ * with the value of pmt::PMT_NIL on the first item it passes, and with
+ * the key pmt::intern("squelch:eob") on the last item it passes.
*/
static sptr make(double db, double alpha=0.0001,
int ramp=0, bool gate=false);
diff --git a/gr-analog/lib/fastnoise_source_X_impl.cc.t b/gr-analog/lib/fastnoise_source_X_impl.cc.t
index c25230dc6a..21f963b65a 100644
--- a/gr-analog/lib/fastnoise_source_X_impl.cc.t
+++ b/gr-analog/lib/fastnoise_source_X_impl.cc.t
@@ -45,7 +45,11 @@ namespace gr {
io_signature::make(0, 0, 0),
io_signature::make(1, 1, sizeof(@TYPE@))),
d_type(type),
+#if @IS_COMPLEX@ // complex?
+ d_ampl(ampl/sqrtf(2.0f)),
+#else
d_ampl(ampl),
+#endif
d_rng(seed)
{
d_samples.resize(samples);
@@ -68,7 +72,11 @@ namespace gr {
@IMPL_NAME@::set_amplitude(float ampl)
{
gr::thread::scoped_lock l(d_setlock);
+#if @IS_COMPLEX@ // complex?
+ d_ampl = ampl/sqrtf(2.0f);
+#else
d_ampl = ampl;
+#endif
generate();
}
@@ -165,4 +173,3 @@ namespace gr {
} /* namespace analog */
} /* namespace gr */
-
diff --git a/gr-analog/lib/noise_source_X_impl.cc.t b/gr-analog/lib/noise_source_X_impl.cc.t
index 960666f14d..d8c1b7eb1b 100644
--- a/gr-analog/lib/noise_source_X_impl.cc.t
+++ b/gr-analog/lib/noise_source_X_impl.cc.t
@@ -45,7 +45,11 @@ namespace gr {
io_signature::make(0, 0, 0),
io_signature::make(1, 1, sizeof(@TYPE@))),
d_type(type),
+#if @IS_COMPLEX@ // complex?
+ d_ampl(ampl/sqrtf(2.0f)),
+#else
d_ampl(ampl),
+#endif
d_rng(seed)
{
}
@@ -65,7 +69,11 @@ namespace gr {
@IMPL_NAME@::set_amplitude(float ampl)
{
gr::thread::scoped_lock l(d_setlock);
+#if @IS_COMPLEX@ // complex?
+ d_ampl = ampl/sqrtf(2.0f);
+#else
d_ampl = ampl;
+#endif
}
int
@@ -129,4 +137,3 @@ namespace gr {
} /* namespace analog */
} /* namespace gr */
-
diff --git a/gr-analog/lib/squelch_base_cc_impl.cc b/gr-analog/lib/squelch_base_cc_impl.cc
index 3255d3bde4..b5c153558b 100644
--- a/gr-analog/lib/squelch_base_cc_impl.cc
+++ b/gr-analog/lib/squelch_base_cc_impl.cc
@@ -32,8 +32,11 @@ namespace gr {
squelch_base_cc_impl::squelch_base_cc_impl(const char *name, int ramp, bool gate)
: block(name,
- io_signature::make(1, 1, sizeof(float)),
- io_signature::make(1, 1, sizeof(float)))
+ io_signature::make(1, 1, sizeof(float)),
+ io_signature::make(1, 1, sizeof(float))),
+ d_sob_key(pmt::intern("squelch_sob")),
+ d_eob_key(pmt::intern("squelch_eob")),
+ d_tag_next_unmuted(true)
{
set_ramp(ramp);
set_gate(gate);
@@ -92,48 +95,58 @@ namespace gr {
gr::thread::scoped_lock l(d_setlock);
for(int i = 0; i < noutput_items; i++) {
- update_state(in[i]);
-
- // Adjust envelope based on current state
- switch(d_state) {
- case ST_MUTED:
- if(!mute()) {
- d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; // If not ramping, go straight to unmuted
- }
- break;
-
- case ST_UNMUTED:
- if(mute()) {
- d_state = d_ramp ? ST_DECAY : ST_MUTED; // If not ramping, go straight to muted
- }
- break;
-
- case ST_ATTACK:
- d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed
- if(d_ramped >= d_ramp) { // use >= in case d_ramp is set to lower value elsewhere
- d_state = ST_UNMUTED;
- d_envelope = 1.0;
- }
- break;
-
- case ST_DECAY:
- d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed
- if(d_ramped == 0.0) {
- d_state = ST_MUTED;
- }
- break;
- };
-
- // If unmuted, copy input times envelope to output
- // Otherwise, if not gating, copy zero to output
- if(d_state != ST_MUTED) {
- out[j++] = in[i]*gr_complex(d_envelope, 0.0);
- }
- else {
- if(!d_gate) {
- out[j++] = 0.0;
- }
- }
+ update_state(in[i]);
+
+ // Adjust envelope based on current state
+ switch(d_state) {
+ case ST_MUTED:
+ if(!mute()) {
+ d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; // If not ramping, go straight to unmuted
+ if(d_state == ST_UNMUTED)
+ d_tag_next_unmuted = true;
+ }
+ break;
+
+ case ST_UNMUTED:
+ if(d_tag_next_unmuted) {
+ d_tag_next_unmuted = false;
+ add_item_tag(0, nitems_written(0) + j, d_sob_key, pmt::PMT_NIL);
+ }
+ if(mute()) {
+ d_state = d_ramp ? ST_DECAY : ST_MUTED; // If not ramping, go straight to muted
+ if(d_state == ST_MUTED)
+ add_item_tag(0, nitems_written(0) + j, d_eob_key, pmt::PMT_NIL);
+ }
+ break;
+
+ case ST_ATTACK:
+ d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed
+ if(d_ramped >= d_ramp) { // use >= in case d_ramp is set to lower value elsewhere
+ d_state = ST_UNMUTED;
+ d_tag_next_unmuted = true;
+ d_envelope = 1.0;
+ }
+ break;
+
+ case ST_DECAY:
+ d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed
+ if(d_ramped == 0.0) {
+ d_state = ST_MUTED;
+ add_item_tag(0, nitems_written(0) + j, d_eob_key, pmt::PMT_NIL);
+ }
+ break;
+ };
+
+ // If unmuted, copy input times envelope to output
+ // Otherwise, if not gating, copy zero to output
+ if(d_state != ST_MUTED) {
+ out[j++] = in[i]*gr_complex(d_envelope, 0.0);
+ }
+ else {
+ if(!d_gate) {
+ out[j++] = 0.0;
+ }
+ }
}
consume_each(noutput_items); // Use all the inputs
diff --git a/gr-analog/lib/squelch_base_cc_impl.h b/gr-analog/lib/squelch_base_cc_impl.h
index 58802df91c..68ed1bb2b8 100644
--- a/gr-analog/lib/squelch_base_cc_impl.h
+++ b/gr-analog/lib/squelch_base_cc_impl.h
@@ -36,6 +36,8 @@ namespace gr {
bool d_gate;
double d_envelope;
enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state;
+ const pmt::pmt_t d_sob_key, d_eob_key;
+ bool d_tag_next_unmuted;
protected:
virtual void update_state(const gr_complex &sample) {};
diff --git a/gr-analog/lib/squelch_base_ff_impl.cc b/gr-analog/lib/squelch_base_ff_impl.cc
index a729fedb24..ea2d29bd97 100644
--- a/gr-analog/lib/squelch_base_ff_impl.cc
+++ b/gr-analog/lib/squelch_base_ff_impl.cc
@@ -26,14 +26,18 @@
#include "squelch_base_ff_impl.h"
#include <gnuradio/io_signature.h>
+#include <pmt/pmt.h>
namespace gr {
namespace analog {
squelch_base_ff_impl::squelch_base_ff_impl(const char *name, int ramp, bool gate)
: block(name,
- io_signature::make(1, 1, sizeof(float)),
- io_signature::make(1, 1, sizeof(float)))
+ io_signature::make(1, 1, sizeof(float)),
+ io_signature::make(1, 1, sizeof(float))),
+ d_sob_key(pmt::intern("squelch_sob")),
+ d_eob_key(pmt::intern("squelch_eob")),
+ d_tag_next_unmuted(true)
{
set_ramp(ramp);
set_gate(gate);
@@ -88,48 +92,61 @@ namespace gr {
int j = 0;
for(int i = 0; i < noutput_items; i++) {
- update_state(in[i]);
-
- // Adjust envelope based on current state
- switch(d_state) {
- case ST_MUTED:
- if(!mute())
- // If not ramping, go straight to unmuted
- d_state = d_ramp ? ST_ATTACK : ST_UNMUTED;
- break;
-
- case ST_UNMUTED:
- if(mute())
- // If not ramping, go straight to muted
- d_state = d_ramp ? ST_DECAY : ST_MUTED;
- break;
-
- case ST_ATTACK:
- // FIXME: precalculate window for speed
- d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0;
-
- // use >= in case d_ramp is set to lower value elsewhere
- if(d_ramped >= d_ramp) {
- d_state = ST_UNMUTED;
- d_envelope = 1.0;
- }
- break;
-
- case ST_DECAY:
- // FIXME: precalculate window for speed
- d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0;
- if(d_ramped == 0.0)
- d_state = ST_MUTED;
- break;
- };
-
- // If unmuted, copy input times envelope to output
- // Otherwise, if not gating, copy zero to output
- if(d_state != ST_MUTED)
- out[j++] = in[i]*d_envelope;
- else
- if(!d_gate)
- out[j++] = 0.0;
+ update_state(in[i]);
+
+ // Adjust envelope based on current state
+ switch(d_state) {
+ case ST_MUTED:
+ if(!mute()) {
+ // If not ramping, go straight to unmuted
+ d_state = d_ramp ? ST_ATTACK : ST_UNMUTED;
+ if(d_state == ST_UNMUTED)
+ d_tag_next_unmuted = true;
+ }
+ break;
+
+ case ST_UNMUTED:
+ if(d_tag_next_unmuted) {
+ d_tag_next_unmuted = false;
+ add_item_tag(0, nitems_written(0) + j, d_sob_key, pmt::PMT_NIL);
+ }
+ if(mute()) {
+ // If not ramping, go straight to muted
+ d_state = d_ramp ? ST_DECAY : ST_MUTED;
+ if(d_state == ST_MUTED)
+ add_item_tag(0, nitems_written(0) + j, d_eob_key, pmt::PMT_NIL);
+ }
+ break;
+
+ case ST_ATTACK:
+ // FIXME: precalculate window for speed
+ d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0;
+
+ // use >= in case d_ramp is set to lower value elsewhere
+ if(d_ramped >= d_ramp) {
+ d_state = ST_UNMUTED;
+ d_tag_next_unmuted = true;
+ d_envelope = 1.0;
+ }
+ break;
+
+ case ST_DECAY:
+ // FIXME: precalculate window for speed
+ d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0;
+ if(d_ramped == 0.0) {
+ d_state = ST_MUTED;
+ add_item_tag(0, nitems_written(0) + j, d_eob_key, pmt::PMT_NIL);
+ }
+ break;
+ };
+
+ // If unmuted, copy input times envelope to output
+ // Otherwise, if not gating, copy zero to output
+ if(d_state != ST_MUTED)
+ out[j++] = in[i]*d_envelope;
+ else
+ if(!d_gate)
+ out[j++] = 0.0;
}
consume_each(noutput_items); // Use all the inputs
diff --git a/gr-analog/lib/squelch_base_ff_impl.h b/gr-analog/lib/squelch_base_ff_impl.h
index 343dc5f610..b6a7efe609 100644
--- a/gr-analog/lib/squelch_base_ff_impl.h
+++ b/gr-analog/lib/squelch_base_ff_impl.h
@@ -24,6 +24,7 @@
#define INCLUDED_GR_SQUELCH_BASE_FF_IMPL_H
#include <gnuradio/analog/squelch_base_ff.h>
+#include <pmt/pmt.h>
namespace gr {
namespace analog {
@@ -36,6 +37,8 @@ namespace gr {
bool d_gate;
double d_envelope;
enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state;
+ const pmt::pmt_t d_sob_key, d_eob_key;
+ bool d_tag_next_unmuted;
protected:
virtual void update_state(const float &sample) {};
diff --git a/gr-audio/grc/audio_sink.xml b/gr-audio/grc/audio_sink.xml
index 9a70006e72..727767b72e 100644
--- a/gr-audio/grc/audio_sink.xml
+++ b/gr-audio/grc/audio_sink.xml
@@ -8,7 +8,7 @@
<name>Audio Sink</name>
<key>audio_sink</key>
<category>Audio</category>
- <throttle>1</throttle>
+ <flags>throttle</flags>
<import>from gnuradio import audio</import>
<make>audio.sink($samp_rate, $device_name, $ok_to_block)</make>
<param>
diff --git a/gr-audio/grc/audio_source.xml b/gr-audio/grc/audio_source.xml
index 0cb73a3ae9..aaa3225e8b 100644
--- a/gr-audio/grc/audio_source.xml
+++ b/gr-audio/grc/audio_source.xml
@@ -8,7 +8,7 @@
<name>Audio Source</name>
<key>audio_source</key>
<category>Audio</category>
- <throttle>1</throttle>
+ <flags>throttle</flags>
<import>from gnuradio import audio</import>
<make>audio.source($samp_rate, $device_name, $ok_to_block)</make>
<param>
diff --git a/gr-blocks/examples/CMakeLists.txt b/gr-blocks/examples/CMakeLists.txt
index bb07cdc2b5..0ecf9d7a91 100644
--- a/gr-blocks/examples/CMakeLists.txt
+++ b/gr-blocks/examples/CMakeLists.txt
@@ -20,6 +20,7 @@
install(
FILES
matrix_multiplexer.grc
+ peak_detector2.grc
vector_source_with_tags.grc
DESTINATION ${GR_PKG_DATA_DIR}/examples/blocks
COMPONENT "runtime_python"
diff --git a/gr-blocks/examples/peak_detector2.grc b/gr-blocks/examples/peak_detector2.grc
new file mode 100644
index 0000000000..c49febdce4
--- /dev/null
+++ b/gr-blocks/examples/peak_detector2.grc
@@ -0,0 +1,1045 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.8'?>
+<flow_graph>
+ <timestamp>Wed Apr 8 18:17:58 2015</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>test_peak2</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>run</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(16, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>factor</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.3</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(264, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>alpha</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.001</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(440, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>lookahead</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>int(samp_rate/1e3/1.1)</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(352, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100e3</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(176, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>512</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-1.5</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>1.5</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>3</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value>Input</value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value>Peaks</value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value>Average</value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(808, 152)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_char_to_float</key>
+ <param>
+ <key>id</key>
+ <value>blocks_char_to_float_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(624, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_peak_detector2_fb</key>
+ <param>
+ <key>id</key>
+ <value>blocks_peak_detector2_fb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>threshold_factor_rise</key>
+ <value>factor</value>
+ </param>
+ <param>
+ <key>look_ahead</key>
+ <value>lookahead</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>alpha</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(408, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_sink</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_sink_0_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>flag.data</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>unbuffered</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>append</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(808, 51)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_sink</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_sink_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>avg.data</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>unbuffered</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>append</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(784, 259)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_sink</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>in.data</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>unbuffered</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>append</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(408, 187)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>offset</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value></value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.1</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>-1.5</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>1.5</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.1</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(16, 235)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_sig_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>analog.GR_SAW_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>offset</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(16, 115)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(224, 147)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>blocks_char_to_float_0</source_block_id>
+ <sink_block_id>blocks_file_sink_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_peak_detector2_fb_0</source_block_id>
+ <sink_block_id>blocks_file_sink_0_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_char_to_float_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_peak_detector2_fb_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>2</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_peak_detector2_fb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_peak_detector2_fb_0</source_block_id>
+ <sink_block_id>blocks_char_to_float_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_file_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_sig_source_x_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index cc7b4b8c6f..fb4e10d1ba 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -51,6 +51,8 @@
</cat>
<cat>
<name>Control Port</name>
+ <block>blocks_ctrlport_monitor</block>
+ <block>blocks_ctrlport_monitor_performance</block>
<block>blocks_ctrlport_probe2_x</block>
<block>blocks_ctrlport_probe2_c</block>
<block>blocks_ctrlport_probe_c</block>
diff --git a/gr-blocks/grc/blocks_ctrlport_performance.xml b/gr-blocks/grc/blocks_ctrlport_performance.xml
new file mode 100644
index 0000000000..ab17c9e263
--- /dev/null
+++ b/gr-blocks/grc/blocks_ctrlport_performance.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+
+<!--
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of GNU Radio
+
+ GNU Radio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Radio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Radio; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street,
+ Boston, MA 02110-1301, USA.
+-->
+
+<block>
+ <name>CtrlPort Performance Monitor</name>
+ <key>blocks_ctrlport_monitor_performance</key>
+ <import>from gnuradio.ctrlport.monitor import *</import>
+ <make>not $en or monitor("gr-perf-monitorx")</make>
+ <param>
+ <name>Enabled</name>
+ <key>en</key>
+ <value></value>
+ <type>enum</type>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
+
+ <doc>
+ Place this in a graph to launch a QtPy GR CtrlPort Performance Monitor app.
+ </doc>
+
+</block>
diff --git a/gr-blocks/grc/blocks_ctrlport_viewer.xml b/gr-blocks/grc/blocks_ctrlport_viewer.xml
new file mode 100644
index 0000000000..1d5a2e5931
--- /dev/null
+++ b/gr-blocks/grc/blocks_ctrlport_viewer.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+
+<!--
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of GNU Radio
+
+ GNU Radio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Radio is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Radio; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street,
+ Boston, MA 02110-1301, USA.
+-->
+
+<block>
+ <name>CtrlPort Monitor</name>
+ <key>blocks_ctrlport_monitor</key>
+ <import>from gnuradio.ctrlport.monitor import *</import>
+ <make>not $en or monitor()</make>
+ <param>
+ <name>Enabled</name>
+ <key>en</key>
+ <value></value>
+ <type>enum</type>
+ <option>
+ <name>True</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>False</name>
+ <key>False</key>
+ </option>
+ </param>
+
+ <doc>
+ Place this in a graph to launch a QtPy GR CtrlPort Monitor app.
+ </doc>
+
+</block>
diff --git a/gr-blocks/grc/blocks_peak_detector2_fb.xml b/gr-blocks/grc/blocks_peak_detector2_fb.xml
index 584e7a1fb3..0b25e01680 100644
--- a/gr-blocks/grc/blocks_peak_detector2_fb.xml
+++ b/gr-blocks/grc/blocks_peak_detector2_fb.xml
@@ -38,4 +38,9 @@
<name>out</name>
<type>byte</type>
</source>
+ <source>
+ <name>debug</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
</block>
diff --git a/gr-blocks/grc/blocks_throttle.xml b/gr-blocks/grc/blocks_throttle.xml
index 790e195750..26f4aa768b 100644
--- a/gr-blocks/grc/blocks_throttle.xml
+++ b/gr-blocks/grc/blocks_throttle.xml
@@ -7,7 +7,7 @@
<block>
<name>Throttle</name>
<key>blocks_throttle</key>
- <throttle>1</throttle>
+ <flags>throttle</flags>
<import>from gnuradio import blocks</import>
<make>blocks.throttle($type.size*$vlen, $samples_per_second,$ignoretag)</make>
<callback>set_sample_rate($samples_per_second)</callback>
diff --git a/gr-blocks/grc/blocks_udp_source.xml b/gr-blocks/grc/blocks_udp_source.xml
index 3b434c107e..03dbb5781b 100644
--- a/gr-blocks/grc/blocks_udp_source.xml
+++ b/gr-blocks/grc/blocks_udp_source.xml
@@ -7,7 +7,7 @@
<block>
<name>UDP Source</name>
<key>blocks_udp_source</key>
- <throttle>1</throttle>
+ <flags>throttle</flags>
<import>from gnuradio import blocks</import>
<make>blocks.udp_source($type.size*$vlen, $ipaddr, $port, $psize, $eof)</make>
<callback>set_mtu($mtu)</callback>
diff --git a/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h b/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h
index da2d9fc740..541dd8aa09 100644
--- a/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h
+++ b/gr-blocks/include/gnuradio/blocks/peak_detector2_fb.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007,2013 Free Software Foundation, Inc.
+ * Copyright 2007,2013,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,7 +36,7 @@ namespace gr {
* \details
* If a peak is detected, this block outputs a 1, or it outputs
* 0's. A separate debug output may be connected, to view the
- * internal EWMA described below.
+ * internal estimated mean described below.
*/
class BLOCKS_API peak_detector2_fb : virtual public sync_block
{
@@ -47,13 +47,21 @@ namespace gr {
/*!
* Build a peak detector block with float in, byte out.
*
- * \param threshold_factor_rise The threshold factor determins
- * when a peak is present. An EWMA average of the signal is
- * calculated and when the value of the signal goes over
- * threshold_factor_rise*average, we call the peak.
+ * \param threshold_factor_rise The threshold factor determines
+ * when a peak is present. An average of the input signal
+ * is calculated (through a single-pole autoregressive
+ * filter) and when the value of the input signal goes
+ * over threshold_factor_rise*average, we assume we are
+ * in the neighborhood of a peak. The block will then
+ * find the position of the maximum within a window of
+ * look_ahead samples starting at the point where the
+ * threshold was crossed upwards.
* \param look_ahead The look-ahead value is used when the
- * threshold is found to locate the peak within this range.
- * \param alpha The gain value of a single-pole moving average filter.
+ * threshold is crossed upwards to locate the peak within
+ * this range.
+ * \param alpha One minus the pole of a single-pole
+ * autoregressive filter that evaluates the average of
+ * the input signal.
*/
static sptr make(float threshold_factor_rise=7,
int look_ahead=1000, float alpha=0.001);
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index cd164f219e..0f5d9fa2b6 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -251,18 +251,20 @@ GR_LIBRARY_FOO(gnuradio-blocks RUNTIME_COMPONENT "blocks_runtime" DEVEL_COMPONEN
if(ENABLE_STATIC_LIBS)
# Remove controlport-specific source files from staticlibs build
if(ENABLE_GR_CTRLPORT)
- list(REMOVE_ITEM gr_blocks_sources
- ${blocks_ctrlport_sources}
- )
+ if(ICE_FOUND)
+ list(REMOVE_ITEM gr_blocks_sources
+ ${blocks_ctrlport_sources}
+ )
- # Remove GR_CTRLPORT set this target's definitions.
- # Makes sure we don't try to use ControlPort stuff in source files
- GET_DIRECTORY_PROPERTY(STATIC_DEFS COMPILE_DEFINITIONS)
- list(REMOVE_ITEM STATIC_DEFS "GR_CTRLPORT")
- SET_PROPERTY(DIRECTORY PROPERTY COMPILE_DEFINITIONS "${STATIC_DEFS}")
+ # Remove GR_CTRLPORT set this target's definitions.
+ # Makes sure we don't try to use ControlPort stuff in source files
+ GET_DIRECTORY_PROPERTY(STATIC_DEFS COMPILE_DEFINITIONS)
+ list(REMOVE_ITEM STATIC_DEFS "GR_CTRLPORT")
+ SET_PROPERTY(DIRECTORY PROPERTY COMPILE_DEFINITIONS "${STATIC_DEFS}")
- # readd it to the target since we removed it from the directory-wide list.
- SET_PROPERTY(TARGET gnuradio-blocks APPEND PROPERTY COMPILE_DEFINITIONS "GR_CTRLPORT")
+ # readd it to the target since we removed it from the directory-wide list.
+ SET_PROPERTY(TARGET gnuradio-blocks APPEND PROPERTY COMPILE_DEFINITIONS "GR_CTRLPORT")
+ endif(ICE_FOUND)
endif(ENABLE_GR_CTRLPORT)
add_library(gnuradio-blocks_static STATIC ${gr_blocks_sources})
diff --git a/gr-blocks/lib/ctrlport_probe2_b_impl.cc b/gr-blocks/lib/ctrlport_probe2_b_impl.cc
index e6e2570ea6..996e997d96 100644
--- a/gr-blocks/lib/ctrlport_probe2_b_impl.cc
+++ b/gr-blocks/lib/ctrlport_probe2_b_impl.cc
@@ -63,39 +63,27 @@ namespace gr {
ninput_items_required[i] = d_len;
}
- // boost::shared_mutex mutex_buffer;
- // mutable boost::mutex mutex_notify;
- // boost::condition_variable condition_buffer_ready;
std::vector<signed char>
ctrlport_probe2_b_impl::get()
{
- mutex_buffer.lock();
- d_buffer.clear();
- mutex_buffer.unlock();
-
- // wait for condition
- boost::mutex::scoped_lock lock(mutex_notify);
- condition_buffer_ready.wait(lock);
-
- mutex_buffer.lock();
- std::vector<signed char> buf_copy = d_buffer;
- assert(buf_copy.size() == d_len);
- mutex_buffer.unlock();
-
- return buf_copy;
+ return buffered_get.get();
}
void
ctrlport_probe2_b_impl::set_length(int len)
{
+ gr::thread::scoped_lock guard(d_setlock);
+
if(len > 8191) {
- std::cerr << "probe2_b: length " << len
- << " exceeds maximum buffer size of 8191" << std::endl;
+ GR_LOG_WARN(d_logger,
+ boost::format("probe2_b: length %1% exceeds maximum"
+ " buffer size of 8191") % len);
len = 8191;
}
d_len = len;
- d_buffer.reserve(d_len);
+ d_buffer.resize(d_len);
+ d_index = 0;
}
int
@@ -111,23 +99,22 @@ namespace gr {
{
const char *in = (const char*)input_items[0];
+ gr::thread::scoped_lock guard(d_setlock);
+
// copy samples to get buffer if we need samples
- mutex_buffer.lock();
- if(d_buffer.size() < d_len) {
+ if(d_index < d_len) {
// copy smaller of remaining buffer space and num inputs to work()
- int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+ int num_copy = std::min( (int)(d_len - d_index), noutput_items );
- // TODO: convert this to a copy operator for speed...
- for(int i = 0; i < num_copy; i++) {
- d_buffer.push_back(in[i]);
- }
+ memcpy(&d_buffer[d_index], in, num_copy*sizeof(char));
+ d_index += num_copy;
+ }
- // notify the waiting get() if we fill up the buffer
- if(d_buffer.size() == d_len) {
- condition_buffer_ready.notify_one();
- }
+ // notify the waiting get() if we fill up the buffer
+ if(d_index == d_len) {
+ buffered_get.offer_data(d_buffer);
+ d_index = 0;
}
- mutex_buffer.unlock();
return noutput_items;
}
diff --git a/gr-blocks/lib/ctrlport_probe2_b_impl.h b/gr-blocks/lib/ctrlport_probe2_b_impl.h
index 155dd4c23c..165f0d33db 100644
--- a/gr-blocks/lib/ctrlport_probe2_b_impl.h
+++ b/gr-blocks/lib/ctrlport_probe2_b_impl.h
@@ -25,7 +25,7 @@
#include <gnuradio/blocks/ctrlport_probe2_b.h>
#include <gnuradio/rpcregisterhelpers.h>
-#include <boost/thread/shared_mutex.hpp>
+#include <gnuradio/rpcbufferedget.h>
namespace gr {
namespace blocks {
@@ -37,11 +37,10 @@ namespace gr {
std::string d_desc;
size_t d_len;
unsigned int d_disp_mask;
- boost::shared_mutex mutex_buffer;
- mutable boost::mutex mutex_notify;
- boost::condition_variable condition_buffer_ready;
+ size_t d_index;
std::vector<signed char> d_buffer;
+ rpcbufferedget< std::vector<signed char> > buffered_get;
public:
ctrlport_probe2_b_impl(const std::string &id, const std::string &desc,
@@ -66,4 +65,3 @@ namespace gr {
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE2_C_IMPL_H */
-
diff --git a/gr-blocks/lib/ctrlport_probe2_c_impl.cc b/gr-blocks/lib/ctrlport_probe2_c_impl.cc
index aa038c0765..b8ed0af444 100644
--- a/gr-blocks/lib/ctrlport_probe2_c_impl.cc
+++ b/gr-blocks/lib/ctrlport_probe2_c_impl.cc
@@ -64,39 +64,27 @@ namespace gr {
ninput_items_required[i] = d_len;
}
- // boost::shared_mutex mutex_buffer;
- // mutable boost::mutex mutex_notify;
- // boost::condition_variable condition_buffer_ready;
std::vector<gr_complex>
ctrlport_probe2_c_impl::get()
{
- mutex_buffer.lock();
- d_buffer.clear();
- mutex_buffer.unlock();
-
- // wait for condition
- boost::mutex::scoped_lock lock(mutex_notify);
- condition_buffer_ready.wait(lock);
-
- mutex_buffer.lock();
- std::vector<gr_complex> buf_copy = d_buffer;
- assert(buf_copy.size() == d_len);
- mutex_buffer.unlock();
-
- return buf_copy;
+ return buffered_get.get();
}
void
ctrlport_probe2_c_impl::set_length(int len)
{
+ gr::thread::scoped_lock guard(d_setlock);
+
if(len > 8191) {
- std::cerr << "probe2_c: length " << len
- << " exceeds maximum buffer size of 8191" << std::endl;
+ GR_LOG_WARN(d_logger,
+ boost::format("probe2_c: length %1% exceeds maximum"
+ " buffer size of 8191") % len);
len = 8191;
}
d_len = len;
- d_buffer.reserve(d_len);
+ d_buffer.resize(d_len);
+ d_index = 0;
}
int
@@ -112,23 +100,22 @@ namespace gr {
{
const gr_complex *in = (const gr_complex*)input_items[0];
+ gr::thread::scoped_lock guard(d_setlock);
+
// copy samples to get buffer if we need samples
- mutex_buffer.lock();
- if(d_buffer.size() < d_len) {
+ if(d_index < d_len) {
// copy smaller of remaining buffer space and num inputs to work()
- int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+ int num_copy = std::min( (int)(d_len - d_index), noutput_items );
- // TODO: convert this to a copy operator for speed...
- for(int i = 0; i < num_copy; i++) {
- d_buffer.push_back(in[i]);
- }
+ memcpy(&d_buffer[d_index], in, num_copy*sizeof(gr_complex));
+ d_index += num_copy;
+ }
- // notify the waiting get() if we fill up the buffer
- if(d_buffer.size() == d_len) {
- condition_buffer_ready.notify_one();
- }
+ // notify the waiting get() if we fill up the buffer
+ if(d_index == d_len) {
+ buffered_get.offer_data(d_buffer);
+ d_index = 0;
}
- mutex_buffer.unlock();
return noutput_items;
}
diff --git a/gr-blocks/lib/ctrlport_probe2_c_impl.h b/gr-blocks/lib/ctrlport_probe2_c_impl.h
index 15ff0f4ea2..119738a481 100644
--- a/gr-blocks/lib/ctrlport_probe2_c_impl.h
+++ b/gr-blocks/lib/ctrlport_probe2_c_impl.h
@@ -25,7 +25,7 @@
#include <gnuradio/blocks/ctrlport_probe2_c.h>
#include <gnuradio/rpcregisterhelpers.h>
-#include <boost/thread/shared_mutex.hpp>
+#include <gnuradio/rpcbufferedget.h>
namespace gr {
namespace blocks {
@@ -37,11 +37,10 @@ namespace gr {
std::string d_desc;
size_t d_len;
unsigned int d_disp_mask;
- boost::shared_mutex mutex_buffer;
- mutable boost::mutex mutex_notify;
- boost::condition_variable condition_buffer_ready;
+ size_t d_index;
std::vector<gr_complex> d_buffer;
+ rpcbufferedget< std::vector<gr_complex> > buffered_get;
public:
ctrlport_probe2_c_impl(const std::string &id, const std::string &desc,
@@ -66,4 +65,3 @@ namespace gr {
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE2_C_IMPL_H */
-
diff --git a/gr-blocks/lib/ctrlport_probe2_f_impl.cc b/gr-blocks/lib/ctrlport_probe2_f_impl.cc
index b53b2dc3cb..ff37401e88 100644
--- a/gr-blocks/lib/ctrlport_probe2_f_impl.cc
+++ b/gr-blocks/lib/ctrlport_probe2_f_impl.cc
@@ -62,39 +62,27 @@ namespace gr {
ninput_items_required[i] = d_len;
}
- // boost::shared_mutex mutex_buffer;
- // mutable boost::mutex mutex_notify;
- // boost::condition_variable condition_buffer_ready;
std::vector<float>
ctrlport_probe2_f_impl::get()
{
- mutex_buffer.lock();
- d_buffer.clear();
- mutex_buffer.unlock();
-
- // wait for condition
- boost::mutex::scoped_lock lock(mutex_notify);
- condition_buffer_ready.wait(lock);
-
- mutex_buffer.lock();
- std::vector<float> buf_copy = d_buffer;
- assert(buf_copy.size() == d_len);
- mutex_buffer.unlock();
-
- return buf_copy;
+ return buffered_get.get();
}
void
ctrlport_probe2_f_impl::set_length(int len)
{
+ gr::thread::scoped_lock guard(d_setlock);
+
if(len > 8191) {
- std::cerr << "probe2_f: length " << len
- << " exceeds maximum buffer size of 8191" << std::endl;
+ GR_LOG_WARN(d_logger,
+ boost::format("probe2_f: length %1% exceeds maximum"
+ " buffer size of 8191") % len);
len = 8191;
}
d_len = len;
- d_buffer.reserve(d_len);
+ d_buffer.resize(d_len);
+ d_index = 0;
}
int
@@ -110,23 +98,22 @@ namespace gr {
{
const float *in = (const float*)input_items[0];
+ gr::thread::scoped_lock guard(d_setlock);
+
// copy samples to get buffer if we need samples
- mutex_buffer.lock();
- if(d_buffer.size() < d_len) {
+ if(d_index < d_len) {
// copy smaller of remaining buffer space and num inputs to work()
- int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+ int num_copy = std::min( (int)(d_len - d_index), noutput_items );
- // TODO: convert this to a copy operator for speed...
- for(int i = 0; i < num_copy; i++) {
- d_buffer.push_back(in[i]);
- }
+ memcpy(&d_buffer[d_index], in, num_copy*sizeof(float));
+ d_index += num_copy;
+ }
- // notify the waiting get() if we fill up the buffer
- if(d_buffer.size() == d_len) {
- condition_buffer_ready.notify_one();
- }
+ // notify the waiting get() if we fill up the buffer
+ if(d_index == d_len) {
+ buffered_get.offer_data(d_buffer);
+ d_index = 0;
}
- mutex_buffer.unlock();
return noutput_items;
}
diff --git a/gr-blocks/lib/ctrlport_probe2_f_impl.h b/gr-blocks/lib/ctrlport_probe2_f_impl.h
index a4aa099237..6aec0789f4 100644
--- a/gr-blocks/lib/ctrlport_probe2_f_impl.h
+++ b/gr-blocks/lib/ctrlport_probe2_f_impl.h
@@ -25,7 +25,7 @@
#include <gnuradio/blocks/ctrlport_probe2_f.h>
#include <gnuradio/rpcregisterhelpers.h>
-#include <boost/thread/shared_mutex.hpp>
+#include <gnuradio/rpcbufferedget.h>
namespace gr {
namespace blocks {
@@ -37,11 +37,10 @@ namespace gr {
std::string d_desc;
size_t d_len;
unsigned int d_disp_mask;
- boost::shared_mutex mutex_buffer;
- mutable boost::mutex mutex_notify;
- boost::condition_variable condition_buffer_ready;
+ size_t d_index;
std::vector<float> d_buffer;
+ rpcbufferedget< std::vector<float> > buffered_get;
public:
ctrlport_probe2_f_impl(const std::string &id, const std::string &desc,
@@ -66,4 +65,3 @@ namespace gr {
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE2_F_IMPL_H */
-
diff --git a/gr-blocks/lib/ctrlport_probe2_i_impl.cc b/gr-blocks/lib/ctrlport_probe2_i_impl.cc
index 77dca2ad0d..7e17d8e8fe 100644
--- a/gr-blocks/lib/ctrlport_probe2_i_impl.cc
+++ b/gr-blocks/lib/ctrlport_probe2_i_impl.cc
@@ -64,39 +64,27 @@ namespace gr {
ninput_items_required[i] = d_len;
}
- // boost::shared_mutex mutex_buffer;
- // mutable boost::mutex mutex_notify;
- // boost::condition_variable condition_buffer_ready;
std::vector<int>
ctrlport_probe2_i_impl::get()
{
- mutex_buffer.lock();
- d_buffer.clear();
- mutex_buffer.unlock();
-
- // wait for condition
- boost::mutex::scoped_lock lock(mutex_notify);
- condition_buffer_ready.wait(lock);
-
- mutex_buffer.lock();
- std::vector<int> buf_copy = d_buffer;
- assert(buf_copy.size() == d_len);
- mutex_buffer.unlock();
-
- return buf_copy;
+ return buffered_get.get();
}
void
ctrlport_probe2_i_impl::set_length(int len)
{
+ gr::thread::scoped_lock guard(d_setlock);
+
if(len > 8191) {
- std::cerr << "probe2_i: length " << len
- << " exceeds maximum buffer size of 8191" << std::endl;
+ GR_LOG_WARN(d_logger,
+ boost::format("probe2_i: length %1% exceeds maximum"
+ " buffer size of 8191") % len);
len = 8191;
}
d_len = len;
- d_buffer.reserve(d_len);
+ d_buffer.resize(d_len);
+ d_index = 0;
}
int
@@ -112,23 +100,22 @@ namespace gr {
{
const int *in = (const int*)input_items[0];
+ gr::thread::scoped_lock guard(d_setlock);
+
// copy samples to get buffer if we need samples
- mutex_buffer.lock();
- if(d_buffer.size() < d_len) {
+ if(d_index < d_len) {
// copy smaller of remaining buffer space and num inputs to work()
- int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+ int num_copy = std::min( (int)(d_len - d_index), noutput_items );
- // TODO: convert this to a copy operator for speed...
- for(int i = 0; i < num_copy; i++) {
- d_buffer.push_back(in[i]);
- }
+ memcpy(&d_buffer[d_index], in, num_copy*sizeof(int));
+ d_index += num_copy;
+ }
- // notify the waiting get() if we fill up the buffer
- if(d_buffer.size() == d_len) {
- condition_buffer_ready.notify_one();
- }
+ // notify the waiting get() if we fill up the buffer
+ if(d_index == d_len) {
+ buffered_get.offer_data(d_buffer);
+ d_index = 0;
}
- mutex_buffer.unlock();
return noutput_items;
}
diff --git a/gr-blocks/lib/ctrlport_probe2_i_impl.h b/gr-blocks/lib/ctrlport_probe2_i_impl.h
index 06493ac23a..2832af07ec 100644
--- a/gr-blocks/lib/ctrlport_probe2_i_impl.h
+++ b/gr-blocks/lib/ctrlport_probe2_i_impl.h
@@ -25,7 +25,7 @@
#include <gnuradio/blocks/ctrlport_probe2_i.h>
#include <gnuradio/rpcregisterhelpers.h>
-#include <boost/thread/shared_mutex.hpp>
+#include <gnuradio/rpcbufferedget.h>
namespace gr {
namespace blocks {
@@ -37,11 +37,10 @@ namespace gr {
std::string d_desc;
size_t d_len;
unsigned int d_disp_mask;
- boost::shared_mutex mutex_buffer;
- mutable boost::mutex mutex_notify;
- boost::condition_variable condition_buffer_ready;
+ size_t d_index;
std::vector<int> d_buffer;
+ rpcbufferedget< std::vector<int> > buffered_get;
public:
ctrlport_probe2_i_impl(const std::string &id, const std::string &desc,
@@ -66,4 +65,3 @@ namespace gr {
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE2_I_IMPL_H */
-
diff --git a/gr-blocks/lib/ctrlport_probe2_s_impl.cc b/gr-blocks/lib/ctrlport_probe2_s_impl.cc
index 6a4ade462c..9924243db0 100644
--- a/gr-blocks/lib/ctrlport_probe2_s_impl.cc
+++ b/gr-blocks/lib/ctrlport_probe2_s_impl.cc
@@ -64,39 +64,27 @@ namespace gr {
ninput_items_required[i] = d_len;
}
- // boost::shared_mutex mutex_buffer;
- // mutable boost::mutex mutex_notify;
- // boost::condition_variable condition_buffer_ready;
std::vector<short>
ctrlport_probe2_s_impl::get()
{
- mutex_buffer.lock();
- d_buffer.clear();
- mutex_buffer.unlock();
-
- // wait for condition
- boost::mutex::scoped_lock lock(mutex_notify);
- condition_buffer_ready.wait(lock);
-
- mutex_buffer.lock();
- std::vector<short> buf_copy = d_buffer;
- assert(buf_copy.size() == d_len);
- mutex_buffer.unlock();
-
- return buf_copy;
+ return buffered_get.get();
}
void
ctrlport_probe2_s_impl::set_length(int len)
{
+ gr::thread::scoped_lock guard(d_setlock);
+
if(len > 8191) {
- std::cerr << "probe2_s: length " << len
- << " exceeds maximum buffer size of 8191" << std::endl;
+ GR_LOG_WARN(d_logger,
+ boost::format("probe2_s: length %1% exceeds maximum"
+ " buffer size of 8191") % len);
len = 8191;
}
d_len = len;
- d_buffer.reserve(d_len);
+ d_buffer.resize(d_len);
+ d_index = 0;
}
int
@@ -112,23 +100,21 @@ namespace gr {
{
const short *in = (const short*)input_items[0];
+ gr::thread::scoped_lock guard(d_setlock);
+
// copy samples to get buffer if we need samples
- mutex_buffer.lock();
- if(d_buffer.size() < d_len) {
+ if(d_index < d_len) {
// copy smaller of remaining buffer space and num inputs to work()
- int num_copy = std::min( (int)(d_len - d_buffer.size()), noutput_items );
+ int num_copy = std::min( (int)(d_len - d_index), noutput_items );
- // TODO: convert this to a copy operator for speed...
- for(int i = 0; i < num_copy; i++) {
- d_buffer.push_back(in[i]);
- }
+ memcpy(&d_buffer[d_index], in, num_copy*sizeof(short));
+ d_index += num_copy;
+ }
- // notify the waiting get() if we fill up the buffer
- if(d_buffer.size() == d_len) {
- condition_buffer_ready.notify_one();
- }
+ // notify the waiting get() if we fill up the buffer
+ if(d_index == d_len) {
+ buffered_get.offer_data(d_buffer);
}
- mutex_buffer.unlock();
return noutput_items;
}
diff --git a/gr-blocks/lib/ctrlport_probe2_s_impl.h b/gr-blocks/lib/ctrlport_probe2_s_impl.h
index 078dd56b73..a608a7898c 100644
--- a/gr-blocks/lib/ctrlport_probe2_s_impl.h
+++ b/gr-blocks/lib/ctrlport_probe2_s_impl.h
@@ -25,7 +25,7 @@
#include <gnuradio/blocks/ctrlport_probe2_s.h>
#include <gnuradio/rpcregisterhelpers.h>
-#include <boost/thread/shared_mutex.hpp>
+#include <gnuradio/rpcbufferedget.h>
namespace gr {
namespace blocks {
@@ -37,11 +37,10 @@ namespace gr {
std::string d_desc;
size_t d_len;
unsigned int d_disp_mask;
- boost::shared_mutex mutex_buffer;
- mutable boost::mutex mutex_notify;
- boost::condition_variable condition_buffer_ready;
+ size_t d_index;
std::vector<short> d_buffer;
+ rpcbufferedget< std::vector<short> > buffered_get;
public:
ctrlport_probe2_s_impl(const std::string &id, const std::string &desc,
@@ -66,4 +65,3 @@ namespace gr {
} /* namespace gr */
#endif /* INCLUDED_CTRLPORT_PROBE2_S_IMPL_H */
-
diff --git a/gr-blocks/lib/peak_detector2_fb_impl.cc b/gr-blocks/lib/peak_detector2_fb_impl.cc
index 7ff7f542ec..dc13e66dbe 100644
--- a/gr-blocks/lib/peak_detector2_fb_impl.cc
+++ b/gr-blocks/lib/peak_detector2_fb_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007,2010,2013 Free Software Foundation, Inc.
+ * Copyright 2007,2010,2013,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -45,15 +45,46 @@ namespace gr {
: sync_block("peak_detector2_fb",
io_signature::make(1, 1, sizeof(float)),
io_signature::make2(1, 2, sizeof(char), sizeof(float))),
- d_threshold_factor_rise(threshold_factor_rise),
- d_look_ahead(look_ahead), d_alpha(alpha), d_avg(0.0f), d_found(false)
+ d_avg(0.0f), d_found(false)
{
+ set_threshold_factor_rise(threshold_factor_rise);
+ set_look_ahead(look_ahead);
+ set_alpha(alpha);
}
peak_detector2_fb_impl::~peak_detector2_fb_impl()
{
}
+ void
+ peak_detector2_fb_impl::set_threshold_factor_rise(float thr)
+ {
+ gr::thread::scoped_lock lock(d_setlock);
+ d_threshold_factor_rise = thr;
+ invalidate();
+ }
+
+ void
+ peak_detector2_fb_impl::set_look_ahead(int look)
+ {
+ gr::thread::scoped_lock lock(d_setlock);
+ d_look_ahead = look;
+ invalidate();
+ }
+
+ void
+ peak_detector2_fb_impl::set_alpha(float alpha)
+ {
+ d_alpha = alpha;
+ }
+
+ void
+ peak_detector2_fb_impl::invalidate()
+ {
+ d_found = false;
+ set_output_multiple(1);
+ }
+
int
peak_detector2_fb_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
@@ -61,53 +92,53 @@ namespace gr {
{
float *iptr = (float *)input_items[0];
char *optr = (char *)output_items[0];
+ float *sigout;
+
+ if(output_items.size() == 2)
+ sigout = (float *)output_items[1];
memset(optr, 0, noutput_items*sizeof(char));
- for(int i = 0; i < noutput_items; i++) {
- if(!d_found) {
- // Have not yet detected presence of peak
+ gr::thread::scoped_lock lock(d_setlock);
+
+ // have not crossed threshold yet
+ if(d_found==false) {
+ for(int i = 0; i < noutput_items; i++) {
+ d_avg = d_alpha*iptr[i] + (1.0f - d_alpha)*d_avg;
+ if(output_items.size() == 2)
+ sigout[i]=d_avg;
if(iptr[i] > d_avg * (1.0f + d_threshold_factor_rise)) {
d_found = true;
- d_look_ahead_remaining = d_look_ahead;
d_peak_val = -(float)INFINITY;
- }
- else {
- d_avg = d_alpha*iptr[i] + (1.0f - d_alpha)*d_avg;
+ set_output_multiple(d_look_ahead);
+ return i;
}
}
- else {
- // Detected presence of peak
+ return noutput_items;
+ } // end d_found==false
+
+ // can complete in this call
+ else if(noutput_items >= d_look_ahead) {
+ for(int i = 0; i < d_look_ahead; i++) {
+ d_avg = d_alpha*iptr[i] + (1.0f - d_alpha)*d_avg;
+ if(output_items.size() == 2)
+ sigout[i]=d_avg;
if(iptr[i] > d_peak_val) {
d_peak_val = iptr[i];
- d_peak_ind = i;
- }
- else if(d_look_ahead_remaining <= 0) {
- optr[d_peak_ind] = 1;
- d_found = false;
- d_avg = iptr[i];
+ d_peak_ind =i;
}
-
- // Have not yet located peak, loop and keep searching.
- d_look_ahead_remaining--;
- }
-
- // Every iteration of the loop, write debugging signal out if
- // connected:
- if(output_items.size() == 2) {
- float *sigout = (float *)output_items[1];
- sigout[i] = d_avg;
}
- } // loop
-
- if(!d_found)
- return noutput_items;
+ optr[d_peak_ind] = 1;
- // else if detected presence, keep searching during the next call to work.
- int tmp = d_peak_ind;
- d_peak_ind = 1;
+ // restart the search
+ invalidate();
+ return d_look_ahead;
+ } // end can complete in this call
- return tmp - 1;
+ // cannot complete in this call
+ else {
+ return 0; // ask for more
+ }
}
} /* namespace blocks */
diff --git a/gr-blocks/lib/peak_detector2_fb_impl.h b/gr-blocks/lib/peak_detector2_fb_impl.h
index f5a8ac1a6b..4e16c93dac 100644
--- a/gr-blocks/lib/peak_detector2_fb_impl.h
+++ b/gr-blocks/lib/peak_detector2_fb_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007,2013 Free Software Foundation, Inc.
+ * Copyright 2007,2013,2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -40,14 +40,16 @@ namespace gr {
float d_avg;
bool d_found;
+ void invalidate();
+
public:
peak_detector2_fb_impl(float threshold_factor_rise,
int look_ahead, float alpha);
~peak_detector2_fb_impl();
- void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; }
- void set_look_ahead(int look) { d_look_ahead = look; }
- void set_alpha(float alpha) { d_alpha = alpha; }
+ void set_threshold_factor_rise(float thr);
+ void set_look_ahead(int look);
+ void set_alpha(float alpha);
float threshold_factor_rise() { return d_threshold_factor_rise; }
int look_ahead() { return d_look_ahead; }
diff --git a/gr-blocks/python/blocks/CMakeLists.txt b/gr-blocks/python/blocks/CMakeLists.txt
index 44977313cf..19d808b1dd 100644
--- a/gr-blocks/python/blocks/CMakeLists.txt
+++ b/gr-blocks/python/blocks/CMakeLists.txt
@@ -43,14 +43,14 @@ if(ENABLE_TESTING)
include(GrTest)
file(GLOB py_qa_test_files "qa_*.py")
- # Force out the controlport QA tests if we've disabled it.
- if(NOT ENABLE_GR_CTRLPORT)
+ # Force out the controlport QA tests if we have no backends to use.
+ if(CTRLPORT_BACKENDS EQUAL 0)
list(REMOVE_ITEM py_qa_test_files
${CMAKE_CURRENT_SOURCE_DIR}/qa_cpp_py_binding.py
${CMAKE_CURRENT_SOURCE_DIR}/qa_cpp_py_binding_set.py
${CMAKE_CURRENT_SOURCE_DIR}/qa_ctrlport_probes.py
)
- endif(NOT ENABLE_GR_CTRLPORT)
+ endif(CTRLPORT_BACKENDS EQUAL 0)
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
diff --git a/gr-blocks/python/blocks/qa_cpp_py_binding.py b/gr-blocks/python/blocks/qa_cpp_py_binding.py
new file mode 100644
index 0000000000..23a5c9b826
--- /dev/null
+++ b/gr-blocks/python/blocks/qa_cpp_py_binding.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013,2015 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+#
+# This program tests mixed python and c++ ctrlport exports in a single app
+#
+
+import sys, time, random, numpy, re
+from gnuradio import gr, gr_unittest, blocks
+
+from gnuradio.ctrlport import GNURadio
+from gnuradio import ctrlport
+import os
+
+def get1():
+ return "success"
+
+def get2():
+ return "failure"
+
+class inc_class:
+ def __init__(self):
+ self.val = 1
+ def pp(self):
+ self.val = self.val+1
+ return self.val
+
+get3 = inc_class()
+
+def get4():
+ random.seed(0)
+ rv = random.random()
+ return rv
+
+def get5():
+ numpy.random.seed(0)
+ samp_t = numpy.random.randn(24)+1j*numpy.random.randn(24);
+ samp_f = numpy.fft.fft(samp_t);
+ log_pow_f = 20*numpy.log10(numpy.abs(samp_f))
+ rv = list(log_pow_f)
+ return rv;
+
+def get6():
+ numpy.random.seed(0)
+ samp_t = numpy.random.randn(1024)+1j*numpy.random.randn(1024);
+ rv = list(samp_t)
+ return rv;
+
+class test_cpp_py_binding(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+ os.environ['GR_CONF_CONTROLPORT_ON'] = 'True'
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+ v1 = gr.RPC_get_string("pyland", "v1", "unit_1_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ v1.activate(get1)
+
+ v2 = gr.RPC_get_string("pyland", "v2", "unit_2_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ v2.activate(get2)
+
+ v3 = gr.RPC_get_int("pyland", "v3", "unit_3_int",
+ "Python Exported Int", 0, 100, 1,
+ gr.DISPNULL)
+ v3.activate(get3.pp)
+
+ v4 = gr.RPC_get_double("pyland", "time", "unit_4_time_double",
+ "Python Exported Double", 0, 1000, 1,
+ gr.DISPNULL)
+ v4.activate(get4)
+
+ v5 = gr.RPC_get_vector_float("pyland", "fvec", "unit_5_float_vector",
+ "Python Exported Float Vector", [], [], [],
+ gr.DISPTIME | gr.DISPOPTCPLX)
+ v5.activate(get5)
+
+ v6 = gr.RPC_get_vector_gr_complex("pyland", "cvec", "unit_6_gr_complex_vector",
+ "Python Exported Complex Vector", [], [], [],
+ gr.DISPXY | gr.DISPOPTSCATTER)
+ v6.activate(get6)
+
+ # print some variables locally
+ val = get1()
+ rval = v1.get()
+ self.assertEqual(val, rval)
+
+ val = get2()
+ rval = v2.get()
+ self.assertEqual(val, rval)
+
+ val = get3.pp()
+ rval = v3.get()
+ self.assertEqual(val+1, rval)
+
+ val = get4()
+ rval = v4.get()
+ self.assertEqual(val, rval)
+
+ val = get5()
+ rval = v5.get()
+ self.assertComplexTuplesAlmostEqual(val, rval, 5)
+
+ val = get6()
+ rval = v6.get()
+ self.assertComplexTuplesAlmostEqual(val, rval, 5)
+
+ def test_002(self):
+ data = range(1,9)
+
+ self.src = blocks.vector_source_c(data)
+ self.p1 = blocks.ctrlport_probe_c("aaa","C++ exported variable")
+ self.p2 = blocks.ctrlport_probe_c("bbb","C++ exported variable")
+ probe_name = self.p2.alias()
+
+ self.tb.connect(self.src, self.p1)
+ self.tb.connect(self.src, self.p2)
+ self.tb.start()
+
+ # Probes return complex values as list of floats with re, im
+ # Imaginary parts of this data set are 0.
+ expected_result = [1, 2, 3, 4,
+ 5, 6, 7, 8]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ # Get all exported knobs
+ ret = radio.getKnobs([probe_name + "::bbb"])
+ for name in ret.keys():
+ result = ret[name].value
+ self.assertEqual(result, expected_result)
+
+ self.tb.stop()
+
+if __name__ == '__main__':
+ gr_unittest.run(test_cpp_py_binding, "test_cpp_py_binding.xml")
diff --git a/gr-blocks/python/blocks/qa_cpp_py_binding_set.py b/gr-blocks/python/blocks/qa_cpp_py_binding_set.py
new file mode 100644
index 0000000000..5b81de08f9
--- /dev/null
+++ b/gr-blocks/python/blocks/qa_cpp_py_binding_set.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+#
+# Copyright 2012,2013,2015 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+#
+# This program tests mixed python and c++ GRCP sets in a single app
+#
+
+import sys, time, random, numpy, re
+from gnuradio import gr, gr_unittest, blocks
+
+from gnuradio.ctrlport import GNURadio
+from gnuradio import ctrlport
+import os
+
+class inc_class:
+ def __init__(self,val):
+ self.val = val;
+
+ def _get(self):
+ #print "returning get (val = %s)"%(str(self.val));
+ return self.val;
+
+ def _set(self,val):
+ #print "updating val to %s"%(str(val));
+ self.val = val;
+ return;
+
+getset1 = inc_class(10);
+getset2 = inc_class(100.0);
+getset3 = inc_class("test");
+
+class test_cpp_py_binding_set(gr_unittest.TestCase):
+ def setUp(self):
+ self.tb = gr.top_block()
+ os.environ['GR_CONF_CONTROLPORT_ON'] = 'True'
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+
+ g1 = gr.RPC_get_int("pyland", "v1", "unit_1_int",
+ "Python Exported Int", 0, 100, 10,
+ gr.DISPNULL)
+ g1.activate(getset1._get)
+ s1 = gr.RPC_get_int("pyland", "v1", "unit_1_int",
+ "Python Exported Int", 0, 100, 10,
+ gr.DISPNULL)
+ s1.activate(getset1._set)
+ time.sleep(0.01)
+
+ # test int variables
+ getset1._set(21)
+ val = getset1._get()
+ rval = g1.get()
+ self.assertEqual(val, rval)
+
+ g2 = gr.RPC_get_float("pyland", "v2", "unit_2_float",
+ "Python Exported Float", -100, 1000.0, 100.0,
+ gr.DISPNULL)
+ g2.activate(getset2._get)
+ s2 = gr.RPC_get_float("pyland", "v2", "unit_2_float",
+ "Python Exported Float", -100, 1000.0, 100.0,
+ gr.DISPNULL)
+ s2.activate(getset2._set)
+ time.sleep(0.01)
+
+ # test float variables
+ getset2._set(123.456)
+ val = getset2._get()
+ rval = g2.get()
+ self.assertAlmostEqual(val, rval, 4)
+
+ g3 = gr.RPC_get_string("pyland", "v3", "unit_3_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ g3.activate(getset3._get)
+ s3 = gr.RPC_get_string("pyland", "v3", "unit_3_string",
+ "Python Exported String", "", "", "",
+ gr.DISPNULL)
+ s3.activate(getset3._set)
+ time.sleep(0.01)
+
+ # test string variables
+ getset3._set("third test")
+ val = getset3._get()
+ rval = g3.get()
+ self.assertEqual(val, rval)
+
+
+ def test_002(self):
+ data = range(1, 10)
+
+ self.src = blocks.vector_source_c(data, True)
+ self.p = blocks.nop(gr.sizeof_gr_complex)
+ self.p.set_ctrlport_test(0);
+ probe_info = self.p.alias()
+
+ self.tb.connect(self.src, self.p)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ self.tb.start()
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get all exported knobs
+ key_name_test = probe_info+"::test"
+ ret = radio.getKnobs([key_name_test,])
+
+ ret[key_name_test].value = 10
+ radio.setKnobs({key_name_test: ret[key_name_test]})
+
+ ret = radio.getKnobs([])
+ result_test = ret[key_name_test].value
+ self.assertEqual(result_test, 10)
+
+ self.tb.stop()
+ self.tb.wait()
+
+if __name__ == '__main__':
+ gr_unittest.run(test_cpp_py_binding_set, "test_cpp_py_binding_set.xml")
diff --git a/gr-blocks/python/blocks/qa_ctrlport_probes.py b/gr-blocks/python/blocks/qa_ctrlport_probes.py
index 91d96010fd..c678846df0 100644
--- a/gr-blocks/python/blocks/qa_ctrlport_probes.py
+++ b/gr-blocks/python/blocks/qa_ctrlport_probes.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2013 Free Software Foundation, Inc.
+# Copyright 2013,2015 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -22,33 +22,225 @@
import sys, time, random, numpy
from gnuradio import gr, gr_unittest, blocks
+import os, struct, re
-import os, struct
+from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
class test_ctrlport_probes(gr_unittest.TestCase):
def setUp(self):
- self.tb = gr.top_block()
os.environ['GR_CONF_CONTROLPORT_ON'] = 'True'
+ self.tb = gr.top_block()
def tearDown(self):
self.tb = None
- def xtest_001(self):
- pass
+ def test_001(self):
+ data = range(1,9)
+
+ self.src = blocks.vector_source_c(data, True)
+ self.probe = blocks.ctrlport_probe2_c("samples","Complex",
+ len(data), gr.DISPNULL)
+ probe_name = self.probe.alias()
+
+ self.tb.connect(self.src, self.probe)
+ self.tb.start()
+
+
+ # Probes return complex values as list of floats with re, im
+ # Imaginary parts of this data set are 0.
+ expected_result = [1, 2, 3, 4,
+ 5, 6, 7, 8]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ # Get all exported knobs
+ ret = radio.getKnobs([probe_name + "::samples"])
+ for name in ret.keys():
+ # Get data in probe, which might be offset; find the
+ # beginning and unwrap.
+ result = ret[name].value
+ i = result.index(complex(1.0, 0.0))
+ result = result[i:] + result[0:i]
+ self.assertComplexTuplesAlmostEqual(expected_result, result, 4)
+
+ self.tb.stop()
+ self.tb.wait()
+
def test_002(self):
- pass
+ data = range(1,9)
+
+ self.src = blocks.vector_source_f(data, True)
+ self.probe = blocks.ctrlport_probe2_f("samples","Floats",
+ len(data), gr.DISPNULL)
+ probe_name = self.probe.alias()
+
+ self.tb.connect(self.src, self.probe)
+ self.tb.start()
+
+ expected_result = [1, 2, 3, 4, 5, 6, 7, 8,]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ # Get all exported knobs
+ ret = radio.getKnobs([probe_name + "::samples"])
+ for name in ret.keys():
+ # Get data in probe, which might be offset; find the
+ # beginning and unwrap.
+ result = ret[name].value
+ i = result.index(1.0)
+ result = result[i:] + result[0:i]
+ self.assertEqual(expected_result, result)
+
+ self.tb.stop()
+ self.tb.wait()
def test_003(self):
- pass
+ data = range(1,9)
+
+ self.src = blocks.vector_source_i(data, True)
+ self.probe = blocks.ctrlport_probe2_i("samples","Integers",
+ len(data), gr.DISPNULL)
+ probe_name = self.probe.alias()
+
+ self.tb.connect(self.src, self.probe)
+ self.tb.start()
+
+ expected_result = [1, 2, 3, 4, 5, 6, 7, 8,]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ # Get all exported knobs
+ ret = radio.getKnobs([probe_name + "::samples"])
+ for name in ret.keys():
+ # Get data in probe, which might be offset; find the
+ # beginning and unwrap.
+ result = ret[name].value
+ i = result.index(1.0)
+ result = result[i:] + result[0:i]
+ self.assertEqual(expected_result, result)
+
+ self.tb.stop()
+ self.tb.wait()
+
def test_004(self):
- pass
+ data = range(1,9)
+
+ self.src = blocks.vector_source_s(data, True)
+ self.probe = blocks.ctrlport_probe2_s("samples","Shorts",
+ len(data), gr.DISPNULL)
+ probe_name = self.probe.alias()
+
+ self.tb.connect(self.src, self.probe)
+ self.tb.start()
+
+ expected_result = [1, 2, 3, 4, 5, 6, 7, 8,]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ # Get all exported knobs
+ ret = radio.getKnobs([probe_name + "::samples"])
+ for name in ret.keys():
+ # Get data in probe, which might be offset; find the
+ # beginning and unwrap.
+ result = ret[name].value
+ i = result.index(1.0)
+ result = result[i:] + result[0:i]
+ self.assertEqual(expected_result, result)
+
+ self.tb.stop()
+ self.tb.wait()
def test_005(self):
- pass
+ data = range(1,9)
+
+ self.src = blocks.vector_source_b(data, True)
+ self.probe = blocks.ctrlport_probe2_b("samples","Bytes",
+ len(data), gr.DISPNULL)
+ probe_name = self.probe.alias()
+
+ self.tb.connect(self.src, self.probe)
+ self.tb.start()
+
+ expected_result = [1, 2, 3, 4, 5, 6, 7, 8,]
+
+ # Make sure we have time for flowgraph to run
+ time.sleep(0.1)
+
+ # Get available endpoint
+ ep = gr.rpcmanager_get().endpoints()[0]
+ hostname = re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1)
+ portnum = re.search("-p (\d+)", ep).group(1)
+ argv = [None, hostname, portnum]
+
+ # Initialize a simple ControlPort client from endpoint
+ from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ radio = radiosys.client
+
+ # Get all exported knobs
+ ret = radio.getKnobs([probe_name + "::samples"])
+ for name in ret.keys():
+ # Get data in probe, which might be offset; find the
+ # beginning and unwrap.
+ result = ret[name].value
+ result = list(struct.unpack(len(result)*'b', result))
+ i = result.index(1)
+ result = result[i:] + result[0:i]
+ self.assertEqual(expected_result, result)
+
+ self.tb.stop()
+ self.tb.wait()
if __name__ == '__main__':
gr_unittest.run(test_ctrlport_probes, "test_ctrlport_probes.xml")
diff --git a/gr-blocks/python/blocks/qa_peak_detector2.py b/gr-blocks/python/blocks/qa_peak_detector2.py
index 475897eac2..d6fd4fe95f 100644
--- a/gr-blocks/python/blocks/qa_peak_detector2.py
+++ b/gr-blocks/python/blocks/qa_peak_detector2.py
@@ -30,18 +30,20 @@ class test_peak_detector2(gr_unittest.TestCase):
def tearDown(self):
self.tb = None
- def test_regen1(self):
+ def test_peak1(self):
+ #print "\n\nTEST 1"
tb = self.tb
- data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
+ n=10
+ data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,)+n*(0,)
expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)+n*(0,)
src = blocks.vector_source_f(data, False)
- regen = blocks.peak_detector2_fb()
+ regen = blocks.peak_detector2_fb(7.0, 25, 0.001)
dst = blocks.vector_sink_b()
tb.connect(src, regen)
@@ -52,5 +54,80 @@ class test_peak_detector2(gr_unittest.TestCase):
self.assertEqual(expected_result, dst_data)
+ def test_peak2(self):
+ #print "\n\nTEST 2"
+ tb = self.tb
+
+ n=10
+ data = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,)+n*(0,)
+
+ expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)+n*(0,)
+
+
+ src = blocks.vector_source_f(data, False)
+ regen = blocks.peak_detector2_fb(7.0, 1000, 0.001) # called with a LONG window
+ dst = blocks.vector_sink_b()
+
+ tb.connect(src, regen)
+ tb.connect(regen, dst)
+ tb.run()
+
+ dst_data = dst.data()
+
+ # here we know that the block will terminate prematurely, so we compare only part of the expected_result
+ self.assertEqual(expected_result[0:len(dst_data)], dst_data)
+
+
+ def test_peak3(self):
+ #print "\n\nTEST 3"
+ tb = self.tb
+
+ l = 8100
+ m = 100
+ n = 10
+ data = l*(0,)+ (10,)+ m*(0,)+(100,)+ n*(0,)
+ expected_result = l*(0,)+ (0,)+ m*(0,)+(1,)+ n*(0,)
+
+
+ src = blocks.vector_source_f(data, False)
+ regen = blocks.peak_detector2_fb(7.0, 105, 0.001)
+ dst = blocks.vector_sink_b()
+
+ tb.connect(src, regen)
+ tb.connect(regen, dst)
+ tb.run()
+
+ dst_data = dst.data()
+
+ self.assertEqual(expected_result, dst_data)
+
+
+ def test_peak4(self):
+ #print "\n\nTEST 4"
+ tb = self.tb
+
+ l = 8100
+ m = 100
+ n = 10
+ data = l*(0,)+ (10,)+ m*(0,)+(100,)+ n*(0,)
+ expected_result = l*(0,)+ (0,)+ m*(0,)+(1,)+ n*(0,)
+
+
+ src = blocks.vector_source_f(data, False)
+ regen = blocks.peak_detector2_fb(7.0, 150, 0.001)
+ dst = blocks.vector_sink_b()
+
+ tb.connect(src, regen)
+ tb.connect(regen, dst)
+ tb.run()
+
+ dst_data = dst.data()
+
+ # here we know that the block will terminate prematurely, so we compare only part of the expected_result
+ self.assertEqual(expected_result[0:len(dst_data)], dst_data)
+
+
if __name__ == '__main__':
gr_unittest.run(test_peak_detector2, "test_peak_detector2.xml")
diff --git a/gr-digital/examples/CMakeLists.txt b/gr-digital/examples/CMakeLists.txt
index 8faad96708..38ee443ab7 100644
--- a/gr-digital/examples/CMakeLists.txt
+++ b/gr-digital/examples/CMakeLists.txt
@@ -31,6 +31,13 @@ GR_PYTHON_INSTALL(PROGRAMS
COMPONENT "digital_python"
)
+install(
+ FILES
+ burst_shaper.grc
+ DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}
+ COMPONENT "digital_python"
+)
+
# Narrowband
GR_PYTHON_INSTALL(PROGRAMS
narrowband/transmit_path.py
@@ -82,6 +89,7 @@ install(
demod/dpsk_loopback.grc
demod/gfsk_loopback.grc
demod/test_corr_and_sync.grc
+ demod/test_corr_est.grc
demod/uhd_corr_and_sync_tx.grc
demod/uhd_corr_and_sync_rx.grc
DESTINATION ${GR_PKG_DIGITAL_EXAMPLES_DIR}/demod
diff --git a/gr-digital/examples/burst_shaper.grc b/gr-digital/examples/burst_shaper.grc
new file mode 100644
index 0000000000..35a98a3267
--- /dev/null
+++ b/gr-digital/examples/burst_shaper.grc
@@ -0,0 +1,880 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.8'?>
+<flow_graph>
+ <timestamp>Fri Apr 17 12:31:57 2015</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>burst_shaper</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>no_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>run</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>window_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>fft.window.hann(10)</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(232, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import pmt</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 99)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>from gnuradio import fft</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(96, 99)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_source_x</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_source_x_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>vector</key>
+ <value>[1.0, -1.0]*15</value>
+ </param>
+ <param>
+ <key>tags</key>
+ <value>[gr.python_to_tag({'offset':0, 'key':pmt.intern('packet_len'), 'value':pmt.from_long(20), 'srcid':pmt.intern('vector_source')})]</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 171)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_source_x</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>vector</key>
+ <value>[complex(1.0), complex(-1.0)]*15</value>
+ </param>
+ <param>
+ <key>tags</key>
+ <value>[gr.python_to_tag({'offset':0, 'key':pmt.intern('packet_len'), 'value':pmt.from_long(20), 'srcid':pmt.intern('vector_source')})]</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 307)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tagged_stream_to_pdu</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tagged_stream_to_pdu_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>tag</key>
+ <value>packet_len</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(632, 163)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_message_debug</key>
+ <param>
+ <key>id</key>
+ <value>blocks_message_debug_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(888, 168)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_message_debug</key>
+ <param>
+ <key>id</key>
+ <value>blocks_message_debug_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(888, 304)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tag_debug</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tag_debug_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>Float</value>
+ </param>
+ <param>
+ <key>filter</key>
+ <value>"packet_len"</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>display</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(632, 211)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tagged_stream_to_pdu</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tagged_stream_to_pdu_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>tag</key>
+ <value>packet_len</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(632, 299)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_burst_shaper_xx</key>
+ <param>
+ <key>id</key>
+ <value>digital_burst_shaper_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value>window_taps</value>
+ </param>
+ <param>
+ <key>pre_padding</key>
+ <value>5</value>
+ </param>
+ <param>
+ <key>post_padding</key>
+ <value>5</value>
+ </param>
+ <param>
+ <key>insert_phasing</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>length_tag_name</key>
+ <value>"packet_len"</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(232, 155)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(456, 187)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_burst_shaper_xx</key>
+ <param>
+ <key>id</key>
+ <value>digital_burst_shaper_xx_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value>window_taps</value>
+ </param>
+ <param>
+ <key>pre_padding</key>
+ <value>5</value>
+ </param>
+ <param>
+ <key>post_padding</key>
+ <value>5</value>
+ </param>
+ <param>
+ <key>insert_phasing</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>length_tag_name</key>
+ <value>"packet_len"</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(232, 291)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(456, 323)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_tag_debug</key>
+ <param>
+ <key>id</key>
+ <value>blocks_tag_debug_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>Complex</value>
+ </param>
+ <param>
+ <key>filter</key>
+ <value>"packet_len"</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>display</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(632, 347)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_tagged_stream_to_pdu_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_source_x_0_0</source_block_id>
+ <sink_block_id>digital_burst_shaper_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_burst_shaper_xx_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_burst_shaper_xx_0_0</source_block_id>
+ <sink_block_id>blocks_throttle_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_source_x_0</source_block_id>
+ <sink_block_id>digital_burst_shaper_xx_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_tagged_stream_to_pdu_1</source_block_id>
+ <sink_block_id>blocks_message_debug_0_0</sink_block_id>
+ <source_key>pdus</source_key>
+ <sink_key>print</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_tagged_stream_to_pdu_0</source_block_id>
+ <sink_block_id>blocks_message_debug_0</sink_block_id>
+ <source_key>pdus</source_key>
+ <sink_key>print</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_tag_debug_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0_0</source_block_id>
+ <sink_block_id>blocks_tagged_stream_to_pdu_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0_0</source_block_id>
+ <sink_block_id>blocks_tag_debug_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-digital/examples/demod/test_corr_est.grc b/gr-digital/examples/demod/test_corr_est.grc
new file mode 100644
index 0000000000..6237565a4b
--- /dev/null
+++ b/gr-digital/examples/demod/test_corr_est.grc
@@ -0,0 +1,3500 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.7'?>
+<flow_graph>
+ <timestamp>Fri Jul 11 16:54:10 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>test_corr_est</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>2000,2000</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>data</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[0]*4+[random.getrandbits(8) for i in range(payload_size)]</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(16, 251)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>rrc_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), eb, 5*sps*nfilts)</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1075, 73)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1074, 9)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>payload_size</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>992</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(101, 73)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>bb_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>firdes.root_raised_cosine(sps, sps, 1, eb, 101)</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(429, 8)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(278, 72)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>matched_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>firdes.root_raised_cosine(nfilts, nfilts, 1, eb, int(11*sps*nfilts))</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(429, 72)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(11, 72)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>gap</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>20000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(202, 72)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>eb</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(346, 72)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>preamble</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>[0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc]</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(279, 8)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>rxmod</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>digital.generic_mod(constel, False, sps, True, eb, False, False)</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 427)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>channels_channel_model</key>
+ <param>
+ <key>id</key>
+ <value>channels_channel_model_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>noise_voltage</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>freq_offset</key>
+ <value>freq_offset</value>
+ </param>
+ <param>
+ <key>epsilon</key>
+ <value>time_offset</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>block_tags</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(772, 158)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(586, 190)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_null_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_null_source_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_outputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>bus_conns</key>
+ <value>[[0,],]</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(402, 322)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>phase</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Phase offset</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>-2*scipy.pi</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>2*scipy.pi</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.1</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>3,1,1,1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(692, 7)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>time_offset</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Timing Offset</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>0.995</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>1.005</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.00001</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>4,1,1,1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(950, 8)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>noise</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Noise</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.005</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>3,0,1,1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(584, 7)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_pfb_clock_sync_xxx</key>
+ <param>
+ <key>id</key>
+ <value>digital_pfb_clock_sync_xxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccf</value>
+ </param>
+ <param>
+ <key>sps</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>loop_bw</key>
+ <value>2*3.14/100.0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>rrc_taps</value>
+ </param>
+ <param>
+ <key>filter_size</key>
+ <value>nfilts</value>
+ </param>
+ <param>
+ <key>init_phase</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>max_dev</key>
+ <value>0.5</value>
+ </param>
+ <param>
+ <key>osps</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(790, 289)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_sub_xx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_sub_xx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1125, 617)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>delay</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>delay</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>90</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>counter_slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>5,0,1,2</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(875, 571)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_char_to_float</key>
+ <param>
+ <key>id</key>
+ <value>blocks_char_to_float_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(752, 517)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_unpack_k_bits_bb</key>
+ <param>
+ <key>id</key>
+ <value>blocks_unpack_k_bits_bb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(576, 517)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_stream_mux</key>
+ <param>
+ <key>id</key>
+ <value>blocks_stream_mux_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>lengths</key>
+ <value>(len(preamble)/8+payload_size), gap/sps/8</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(390, 504)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_null_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_null_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_outputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>bus_conns</key>
+ <value>[[0,],]</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(210, 538)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_delay</key>
+ <param>
+ <key>id</key>
+ <value>blocks_delay_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>delay</key>
+ <value>int(delay)</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(923, 518)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_char_to_float</key>
+ <param>
+ <key>id</key>
+ <value>blocks_char_to_float_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>scale</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1112, 482)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>20000</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>3</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>2,0,1,2</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_TAG</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0.010</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>time_est</value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1345, 531)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_constellation_decoder_cb</key>
+ <param>
+ <key>id</key>
+ <value>digital_constellation_decoder_cb_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>constel</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1111, 433)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_costas_loop_cc</key>
+ <param>
+ <key>id</key>
+ <value>digital_costas_loop_cc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>w</key>
+ <value>1*3.14/50.0</value>
+ </param>
+ <param>
+ <key>order</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>use_snr</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1091, 303)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>50000</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>0,0,1,1</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_TAG</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0.1</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>time_est</value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1398, 370)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_constellation</key>
+ <param>
+ <key>id</key>
+ <value>constel</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>sym_map</key>
+ <value>[0,1]</value>
+ </param>
+ <param>
+ <key>const_points</key>
+ <value>[1,-1]</value>
+ </param>
+ <param>
+ <key>rot_sym</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>dims</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>precision</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>soft_dec_lut</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1237, 27)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_range</key>
+ <param>
+ <key>id</key>
+ <value>freq_offset</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Frequency Offset</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>start</key>
+ <value>-0.001</value>
+ </param>
+ <param>
+ <key>stop</key>
+ <value>0.001</value>
+ </param>
+ <param>
+ <key>step</key>
+ <value>0.00002</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>slider</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ </param>
+ <param>
+ <key>min_len</key>
+ <value>200</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>4,0,1,1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(808, 7)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_const_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_const_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>(len(preamble)+payload_size)*8</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>xmin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>xmax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>0,1,1,1</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_TAG</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>time_est</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1399, 283)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_complex_to_mag</key>
+ <param>
+ <key>id</key>
+ <value>blocks_complex_to_mag_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1235, 149)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_complex_to_float</key>
+ <param>
+ <key>id</key>
+ <value>blocks_complex_to_float_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1235, 194)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import scipy</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(181, 16)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>import</key>
+ <param>
+ <key>id</key>
+ <value>import_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>import</key>
+ <value>import random</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(176, 147)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_source_x</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_source_x_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>vector</key>
+ <value>preamble+data</value>
+ </param>
+ <param>
+ <key>tags</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(15, 165)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_constellation_modulator</key>
+ <param>
+ <key>id</key>
+ <value>digital_constellation_modulator_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>constel</value>
+ </param>
+ <param>
+ <key>differential</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>samples_per_symbol</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>excess_bw</key>
+ <value>eb</value>
+ </param>
+ <param>
+ <key>verbose</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>log</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(312, 166)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_stream_mux</key>
+ <param>
+ <key>id</key>
+ <value>blocks_stream_mux_0_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>lengths</key>
+ <value>(len(preamble)+len(data))*8*sps, gap</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(568, 288)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_time_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_time_sink_x_1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ylabel</key>
+ <value>Amplitude</value>
+ </param>
+ <param>
+ <key>yunit</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>80000</value>
+ </param>
+ <param>
+ <key>srate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-200</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>400</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>3</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>entags</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>1,0,1,2</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_NORM</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>100</value>
+ </param>
+ <param>
+ <key>tr_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value>|corr|^2</value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value>Re{corr}</value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value>Im{corr}</value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>-1</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1433, 160)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_modulate_vector</key>
+ <param>
+ <key>id</key>
+ <value>modulated_sync_word</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>mod</key>
+ <value>rxmod</value>
+ </param>
+ <param>
+ <key>data</key>
+ <value>preamble</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>[1]</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 491)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_corr_est_cc</key>
+ <param>
+ <key>id</key>
+ <value>digital_corr_est_cc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>symbols</key>
+ <value>modulated_sync_word</value>
+ </param>
+ <param>
+ <key>sps</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>mark_delay</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>threshold</key>
+ <value>0.9</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(972, 174)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>digital_constellation_decoder_cb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_complex_to_float_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_complex_to_mag_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_corr_est_cc_0</source_block_id>
+ <sink_block_id>digital_pfb_clock_sync_xxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_null_source_0_0</source_block_id>
+ <sink_block_id>blocks_stream_mux_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_stream_mux_0_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_complex_to_float_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_1</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>2</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>channels_channel_model_0</source_block_id>
+ <sink_block_id>digital_corr_est_cc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_constellation_modulator_0</source_block_id>
+ <sink_block_id>blocks_stream_mux_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_corr_est_cc_0</source_block_id>
+ <sink_block_id>blocks_complex_to_mag_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_corr_est_cc_0</source_block_id>
+ <sink_block_id>blocks_complex_to_float_0</sink_block_id>
+ <source_key>1</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>channels_channel_model_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_pfb_clock_sync_xxx_0</source_block_id>
+ <sink_block_id>digital_costas_loop_cc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_delay_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_char_to_float_0_0</source_block_id>
+ <sink_block_id>blocks_sub_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_delay_0</source_block_id>
+ <sink_block_id>blocks_sub_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_sub_xx_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>2</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_char_to_float_0_0</source_block_id>
+ <sink_block_id>qtgui_time_sink_x_0_1</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_stream_mux_0</source_block_id>
+ <sink_block_id>blocks_unpack_k_bits_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_unpack_k_bits_bb_0</source_block_id>
+ <sink_block_id>blocks_char_to_float_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_null_source_0</source_block_id>
+ <sink_block_id>blocks_stream_mux_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_char_to_float_0</source_block_id>
+ <sink_block_id>blocks_delay_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_constellation_decoder_cb_0</source_block_id>
+ <sink_block_id>blocks_char_to_float_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>qtgui_const_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_source_x_0_0</source_block_id>
+ <sink_block_id>digital_constellation_modulator_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml
index f6dcceb6d0..6707a8e4db 100644
--- a/gr-digital/grc/digital_block_tree.xml
+++ b/gr-digital/grc/digital_block_tree.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
- Copyright 2011-2013 Free Software Foundation, Inc.
+ Copyright 2011-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
@@ -63,6 +63,7 @@
<block>digital_constellation_receiver_cb</block>
<block>variable_constellation</block>
<block>variable_constellation_rect</block>
+ <block>variable_modulate_vector</block>
</cat>
<cat>
<name>Packet Operators</name>
@@ -120,6 +121,7 @@
<block>digital_mpsk_receiver_cc</block>
<block>digital_pfb_clock_sync_xxx</block>
<block>digital_pn_correlator_cc</block>
+ <block>digital_corr_est_cc</block>
<block>digital_correlate_and_sync_cc</block>
</cat>
<cat>
diff --git a/gr-digital/grc/digital_burst_shaper.xml b/gr-digital/grc/digital_burst_shaper.xml
new file mode 100644
index 0000000000..5c0bc78d0a
--- /dev/null
+++ b/gr-digital/grc/digital_burst_shaper.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<block>
+ <name>Burst Shaper</name>
+ <key>digital_burst_shaper_xx</key>
+ <category>Packet Operators</category>
+ <import>from gnuradio import digital</import>
+ <make>digital.burst_shaper_$(type.fcn)($window, $pre_padding, $post_padding, $insert_phasing, $length_tag_name)</make>
+ <param>
+ <name>Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>fcn:ff</opt>
+ <opt>taps:float_vector</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>fcn:cc</opt>
+ <opt>taps:complex_vector</opt>
+ </option>
+ </param>
+ <param>
+ <name>Window Taps</name>
+ <key>window</key>
+ <value>([])</value>
+ <type>$(type.taps)</type>
+ </param>
+ <param>
+ <name>Pre-padding Length</name>
+ <key>pre_padding</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Post-padding Length</name>
+ <key>post_padding</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Insert phasing symbols</name>
+ <key>insert_phasing</key>
+ <value>False</value>
+ <type>enum</type>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ </param>
+ <param>
+ <name>Length Tag Name</name>
+ <key>length_tag_name</key>
+ <value>"packet_len"</value>
+ <type>string</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_corr_est_cc.xml b/gr-digital/grc/digital_corr_est_cc.xml
new file mode 100644
index 0000000000..cb345e933f
--- /dev/null
+++ b/gr-digital/grc/digital_corr_est_cc.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<block>
+ <name>Correlation Estimator</name>
+ <key>digital_corr_est_cc</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.corr_est_cc($symbols, $sps, $mark_delay, $threshold)</make>
+ <callback>set_mark_delay($mark_delay)</callback>
+ <callback>set_theshold($threshold)</callback>
+
+ <param>
+ <name>Symbols</name>
+ <key>symbols</key>
+ <type>complex_vector</type>
+ </param>
+
+ <param>
+ <name>Samples per Symbol</name>
+ <key>sps</key>
+ <type>float</type>
+ </param>
+
+ <param>
+ <name>Tag marking delay</name>
+ <key>mark_delay</key>
+ <type>int</type>
+ </param>
+
+ <param>
+ <name>Threshold</name>
+ <key>threshold</key>
+ <value>0.9</value>
+ <type>float</type>
+ </param>
+
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+
+ <source>
+ <name>corr</name>
+ <type>complex</type>
+ <optional>1</optional>
+ </source>
+</block>
diff --git a/gr-digital/grc/digital_modulate_vector.xml b/gr-digital/grc/digital_modulate_vector.xml
new file mode 100644
index 0000000000..91614dd3fd
--- /dev/null
+++ b/gr-digital/grc/digital_modulate_vector.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+# modulate_vector_bc
+###################################################
+ -->
+<block>
+ <name>Modulate Vector</name>
+ <key>variable_modulate_vector</key>
+ <category>Modulators</category>
+ <import>from gnuradio import digital</import>
+ <var_make>self.$(id) = $(id) = digital.modulate_vector_bc($mod .to_basic_block(), $data, $taps)</var_make>
+ <var_value>digital.modulate_vector_bc($mod .to_basic_block(), $data, $taps)</var_value>
+ <make></make>
+
+ <param>
+ <name>Modulator</name>
+ <key>mod</key>
+ <value></value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>Data vector</name>
+ <key>data</key>
+ <value></value>
+ <type>int_vector</type>
+ </param>
+ <param>
+ <name>Filter taps</name>
+ <key>taps</key>
+ <value></value>
+ <type>float_vector</type>
+ </param>
+</block>
diff --git a/gr-digital/grc/digital_msk_timing_recovery_cc.xml b/gr-digital/grc/digital_msk_timing_recovery_cc.xml
new file mode 100644
index 0000000000..cda780d685
--- /dev/null
+++ b/gr-digital/grc/digital_msk_timing_recovery_cc.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<block>
+ <name>MSK Timing Recovery</name>
+ <key>digital_msk_timing_recovery_cc</key>
+ <import>from gnuradio import digital</import>
+ <make>digital.msk_timing_recovery_cc($sps, $gain, $limit, $osps)</make>
+ <callback>set_gain($gain)</callback>
+ <callback>set_sps($sps)</callback>
+ <callback>set_limit($limit)</callback>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Samples per symbol</name>
+ <key>sps</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Error limit</name>
+ <key>limit</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Output samples per symbol</name>
+ <key>osps</key>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ </source>
+ <source>
+ <name>err</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+ <source>
+ <name>omega</name>
+ <type>float</type>
+ <optional>1</optional>
+ </source>
+
+</block>
diff --git a/gr-digital/include/gnuradio/digital/CMakeLists.txt b/gr-digital/include/gnuradio/digital/CMakeLists.txt
index c39b12bed2..d8fe2b6c4d 100644
--- a/gr-digital/include/gnuradio/digital/CMakeLists.txt
+++ b/gr-digital/include/gnuradio/digital/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2011-2014 Free Software Foundation, Inc.
+# Copyright 2011-2015 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -22,6 +22,7 @@
#######################################################################
include(GrMiscUtils)
GR_EXPAND_X_H(digital chunks_to_symbols_XX bf bc sf sc if ic)
+GR_EXPAND_X_H(digital burst_shaper_XX cc ff)
add_custom_target(digital_generated_includes DEPENDS
${generated_includes}
@@ -42,6 +43,7 @@ install(FILES
constellation_decoder_cb.h
constellation_receiver_cb.h
constellation_soft_decoder_cf.h
+ corr_est_cc.h
correlate_access_code_bb.h
correlate_access_code_tag_bb.h
correlate_access_code_bb_ts.h
@@ -69,9 +71,11 @@ install(FILES
lms_dd_equalizer_cc.h
map_bb.h
metric_type.h
+ modulate_vector.h
mpsk_receiver_cc.h
mpsk_snr_est.h
mpsk_snr_est_cc.h
+ msk_timing_recovery_cc.h
ofdm_carrier_allocator_cvc.h
ofdm_chanest_vcvc.h
ofdm_cyclic_prefixer.h
diff --git a/gr-digital/include/gnuradio/digital/burst_shaper_XX.h.t b/gr-digital/include/gnuradio/digital/burst_shaper_XX.h.t
new file mode 100644
index 0000000000..fd7b69060e
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/burst_shaper_XX.h.t
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Burst shaper block for applying burst padding and ramping.
+ * \ingroup packet_operators_blk
+ *
+ * \details
+ *
+ * This block applies a configurable amount of zero padding before
+ * and/or after a burst indicated by tagged stream length tags.
+ *
+ * If phasing symbols are used, an alternating pattern of +1/-1
+ * symbols of length ceil(N/2) will be inserted before and after
+ * each burst, where N is the length of the taps vector. The ramp-
+ * up/ramp-down shape will be applied to these phasing symbols.
+ *
+ * If phasing symbols are not used, the taper will be applied
+ * directly to the head and tail of each burst.
+ *
+ * Length tags will be updated to include the length of any added
+ * zero padding or phasing symbols and will be placed at the
+ * beginning of the modified tagged stream. Any other tags found at
+ * the same offset as a length tag will also be placed at the
+ * beginning of the modified tagged stream, since these tags are
+ * assumed to be associated with the burst rather than a specific
+ * sample. For example, if "tx_time" tags are used to control
+ * bursts, their offsets should be consistent with their associated
+ * burst's length tags. Tags at other offsets will be placed with
+ * the samples on which they were found.
+ *
+ * \li input: stream of @I_TYPE@
+ * \li output: stream of @O_TYPE@
+ */
+ class DIGITAL_API @NAME@ : virtual public block
+ {
+ public:
+ // gr::digital::@BASE_NAME@::sptr
+ typedef boost::shared_ptr<@BASE_NAME@> sptr;
+
+ /*!
+ * Make a burst shaper block.
+ *
+ * \param taps: vector of window taper taps; the first ceil(N/2)
+ * items are the up flank and the last ceil(N/2)
+ * items are the down flank. If taps.size() is odd,
+ * the middle tap will be used as the last item of
+ * the up flank and first item of the down flank.
+ * \param pre_padding: number of zero samples to insert before
+ * the burst.
+ * \param post_padding: number of zero samples to append after
+ * the burst.
+ * \param insert_phasing: if true, insert alternating +1/-1
+ * pattern of length ceil(N/2) before and
+ * after the burst and apply ramp up and
+ * ramp down taps, respectively, to the
+ * inserted patterns instead of the head
+ * and tail items of the burst.
+ * \param length_tag_name: the name of the tagged stream length
+ * tag key.
+ */
+ static sptr make(const std::vector<@O_TYPE@> &taps,
+ int pre_padding=0, int post_padding=0,
+ bool insert_phasing=false,
+ const std::string &length_tag_name="packet_len");
+
+ /*!
+ * Returns the amount of zero padding inserted before each burst.
+ */
+ virtual int pre_padding() const = 0;
+
+ /*!
+ * Returns the amount of zero padding inserted after each burst.
+ */
+ virtual int post_padding() const = 0;
+
+ /*!
+ * Returns the total amount of zero padding and phasing symbols
+ * inserted before each burst.
+ */
+ virtual int prefix_length() const = 0;
+
+ /*!
+ * Returns the total amount of zero padding and phasing symbols
+ * inserted after each burst.
+ */
+ virtual int suffix_length() const = 0;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-digital/include/gnuradio/digital/corr_est_cc.h b/gr-digital/include/gnuradio/digital/corr_est_cc.h
new file mode 100644
index 0000000000..e8211cf60b
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/corr_est_cc.h
@@ -0,0 +1,118 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CORR_EST_CC_CC_H
+#define INCLUDED_DIGITAL_CORR_EST_CC_CC_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Correlate stream with a pre-defined sequence and estimate peak
+ * \ingroup synchronizers_blk
+ *
+ * \details
+ * Input:
+ * \li Stream of complex samples.
+ *
+ * Output:
+ * \li Output stream that just passes the input complex samples
+ * \li tag 'phase_est': estimate of phase offset
+ * \li tag 'time_est': estimate of symbol timing offset
+ * \li tag 'corr_est': the correlation value of the estimates
+ * \li tag 'corr_start': the start sample of the correlation and the value
+ *
+ * \li Optional 2nd output stream providing the advanced correlator output
+ *
+ * This block is designed to search for a sync word by correlation
+ * and uses the results of the correlation to get a time and phase
+ * offset estimate. These estimates are passed downstream as
+ * stream tags for use by follow-on synchronization blocks.
+ *
+ * The sync word is provided as a set of symbols along with a
+ * baseband matched filter which we use to create the filtered and
+ * upsampled symbols that we will receive over-the-air.
+ *
+ * The phase_est tag can be used by downstream blocks to adjust
+ * their phase estimatopm/correction loops, and is currently
+ * implemented by the gr::digital::costas_loop_cc block.
+ *
+ * The time_est tag can be used to adjust the sampling timing
+ * estimate of any downstream synchronization blocks and is
+ * currently implemented by the gr::digital::pfb_clock_sync_ccf
+ * block.
+ *
+ * The caller must provide a "time_est" and "phase_est" tag
+ * marking delay from the start of the correlated signal segment,
+ * in order to mark the proper point in the sync word for
+ * downstream synchronization blocks. Generally this block cannot
+ * know where the actual sync word symbols are located relative to
+ * "corr_start", given that some modulations have pulses with
+ * intentional ISI. The user should manually examine the primary
+ * output and the "corr_start" tag postition to determine the
+ * required tag delay settings for the particular modulation,
+ * sync word, and downstream blocks used.
+ *
+ * For a discussion of the properties of complex correlations,
+ * with respect to signal processing, see:
+ * Marple, Jr., S. L., "Estimating Group Delay and Phase Delay
+ * via Discrete-Time 'Analytic' Cross-Correlation, _IEEE_Transcations_
+ * _on_Signal_Processing_, Volume 47, No. 9, September 1999
+ *
+ */
+ class DIGITAL_API corr_est_cc : virtual public sync_block
+ {
+ public:
+ typedef boost::shared_ptr<corr_est_cc> sptr;
+
+ /*!
+ * Make a block that correlates against the \p symbols vector
+ * and outputs a phase and symbol timing estimate.
+ *
+ * \param symbols Set of symbols to correlate against (e.g., a
+ * sync word).
+ * \param sps Samples per symbol
+ * \param mark_delay tag marking delay in samples after the
+ * corr_start tag
+ * \param threshold Threshold of correlator, relative to a 100%
+ * correlation (1.0). Default is 0.9.
+ */
+ static sptr make(const std::vector<gr_complex> &symbols,
+ float sps, unsigned int mark_delay, float threshold=0.9);
+
+ virtual std::vector<gr_complex> symbols() const = 0;
+ virtual void set_symbols(const std::vector<gr_complex> &symbols) = 0;
+
+ virtual unsigned int mark_delay() const = 0;
+ virtual void set_mark_delay(unsigned int mark_delay) = 0;
+
+ virtual float threshold() const = 0;
+ virtual void set_threshold(float threshold) = 0;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_CORR_EST_CC_H */
diff --git a/gr-digital/include/gnuradio/digital/modulate_vector.h b/gr-digital/include/gnuradio/digital/modulate_vector.h
new file mode 100644
index 0000000000..6083099a89
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/modulate_vector.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_MODULATE_VECTOR_H
+#define INCLUDED_DIGITAL_MODULATE_VECTOR_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/types.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief Modulate a vector of data and apply a shaping filter.
+ *
+ * \p modulator: Pointer to a byte-to-complex modulator block.
+ * \p data: Vector of bytes to modulate into symbols.
+ * \p taps: Post-modulation symbol shaping filter taps.
+ *
+ * \details
+ * This function modulates the input vector and applies a
+ * symbol shaping filter. It is intended for use with the
+ * corr_est_cc block as the symbol stream to correlate
+ * against.
+ *
+ * Any differential encoding or other data coding must be
+ * performed on the input vector before this modulation
+ * operation.
+ *
+ * Be aware that the format of the incoming data must match
+ * the format the modulator block is expecting. GNURadio
+ * modulator blocks are inconsistent in their data type
+ * expectations. For instance, cpmmod_bc expects unpacked,
+ * signed bytes in (-1, 1), while gmsk_mod expects packed,
+ * unsigned bytes in (0, 1). In other words, the output of
+ * gmsk_mod given the input vector [0xaa, 0x00] is equivalent
+ * to the output of cpmmod_bc given the input vector
+ * [1,255,1,255,1,255,1,255,255,255,255,255,255,255,255,255]
+ *
+ * Please check the documentation or source of the modulator
+ * before using this function.
+ *
+ */
+ DIGITAL_API std::vector<gr_complex>
+ modulate_vector_bc(basic_block_sptr modulator,
+ std::vector<uint8_t> data,
+ std::vector<float> taps);
+
+ } /* namespace digital */
+} /* namespace gr */
+
+#endif /* INCLUDED_DIGITAL_MODULATE_VECTOR_H */
diff --git a/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h b/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h
new file mode 100644
index 0000000000..770bd91da1
--- /dev/null
+++ b/gr-digital/include/gnuradio/digital/msk_timing_recovery_cc.h
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_H
+#define INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_H
+
+#include <gnuradio/digital/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace digital {
+
+ /*!
+ * \brief MSK/GMSK timing recovery
+ * \ingroup synchronizers_blk
+ *
+ * This block performs timing synchronization on CPM modulations using a
+ * fourth-order nonlinearity feedback method which is non-data-aided. The
+ * block does not require prior phase synchronization but is relatively
+ * sensitive to frequency offset (keep offset to 0.1x symbol rate).
+ *
+ * For details on the algorithm, see:
+ * A.N. D'Andrea, U. Mengali, R. Reggiannini: A digital approach to clock
+ * recovery in generalized minimum shift keying. IEEE Transactions on
+ * Vehicular Technology, Vol. 39, Issue 3.
+ */
+ class DIGITAL_API msk_timing_recovery_cc : virtual public gr::block
+ {
+ public:
+ typedef boost::shared_ptr<msk_timing_recovery_cc> sptr;
+
+ /*!
+ * \brief Make an MSK timing recovery block.
+ *
+ * \param sps: Samples per symbol
+ * \param gain: Loop gain of timing error filter (try 0.05)
+ * \param limit: Relative limit of timing error (try 0.1 for 10% error max)
+ * \param osps: Output samples per symbol
+ *
+ */
+ static sptr make(float sps, float gain, float limit, int osps);
+
+ virtual void set_gain(float gain)=0;
+ virtual float get_gain(void)=0;
+
+ virtual void set_limit(float limit)=0;
+ virtual float get_limit(void)=0;
+
+ virtual void set_sps(float sps)=0;
+ virtual float get_sps(void)=0;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_H */
+
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt
index eb1008423b..daa577f56f 100644
--- a/gr-digital/lib/CMakeLists.txt
+++ b/gr-digital/lib/CMakeLists.txt
@@ -45,6 +45,7 @@ endif(ENABLE_GR_CTRLPORT)
########################################################################
include(GrMiscUtils)
GR_EXPAND_X_CC_H(digital chunks_to_symbols_XX_impl bf bc sf sc if ic)
+GR_EXPAND_X_CC_H(digital burst_shaper_XX_impl cc ff)
########################################################################
# Setup library
@@ -60,6 +61,7 @@ list(APPEND digital_sources
constellation_decoder_cb_impl.cc
constellation_receiver_cb_impl.cc
constellation_soft_decoder_cf_impl.cc
+ corr_est_cc_impl.cc
correlate_access_code_bb_impl.cc
correlate_access_code_tag_bb_impl.cc
correlate_access_code_bb_ts_impl.cc
@@ -85,9 +87,11 @@ list(APPEND digital_sources
kurtotic_equalizer_cc_impl.cc
lms_dd_equalizer_cc_impl.cc
map_bb_impl.cc
+ modulate_vector.cc
mpsk_receiver_cc_impl.cc
mpsk_snr_est.cc
mpsk_snr_est_cc_impl.cc
+ msk_timing_recovery_cc_impl.cc
ofdm_carrier_allocator_cvc_impl.cc
ofdm_chanest_vcvc_impl.cc
ofdm_cyclic_prefixer_impl.cc
diff --git a/gr-digital/lib/burst_shaper_XX_impl.cc.t b/gr-digital/lib/burst_shaper_XX_impl.cc.t
new file mode 100644
index 0000000000..85add49115
--- /dev/null
+++ b/gr-digital/lib/burst_shaper_XX_impl.cc.t
@@ -0,0 +1,353 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <boost/format.hpp>
+#include <gnuradio/io_signature.h>
+#include <volk/volk.h>
+#include "@IMPL_NAME@.h"
+
+#ifndef VOLK_MULT_gr_complex
+#define VOLK_MULT_gr_complex volk_32fc_x2_multiply_32fc
+#endif
+#ifndef VOLK_MULT_float
+#define VOLK_MULT_float volk_32f_x2_multiply_32f
+#endif
+
+namespace gr {
+ namespace digital {
+
+ @BASE_NAME@::sptr
+ @BASE_NAME@::make(const std::vector<@I_TYPE@> &taps,
+ int pre_padding, int post_padding,
+ bool insert_phasing,
+ const std::string &length_tag_name)
+ {
+ return gnuradio::get_initial_sptr
+ (new @IMPL_NAME@(taps, pre_padding, post_padding,
+ insert_phasing, length_tag_name));
+ }
+
+ @IMPL_NAME@::@IMPL_NAME@(const std::vector<@I_TYPE@> &taps,
+ int pre_padding, int post_padding,
+ bool insert_phasing,
+ const std::string &length_tag_name)
+ : gr::block("@BASE_NAME@",
+ gr::io_signature::make(1, 1, sizeof(@I_TYPE@)),
+ gr::io_signature::make(1, 1, sizeof(@O_TYPE@))),
+ d_up_ramp(taps.begin(), taps.begin() + taps.size()/2 + taps.size()%2),
+ d_down_ramp(taps.begin() + taps.size()/2, taps.end()),
+ d_nprepad(pre_padding),
+ d_npostpad(post_padding),
+ d_insert_phasing(insert_phasing),
+ d_length_tag_key(pmt::string_to_symbol(length_tag_name)),
+ d_ncopy(0),
+ d_limit(0),
+ d_index(0),
+ d_length_tag_offset(0),
+ d_finished(false),
+ d_state(STATE_WAIT)
+ {
+ assert(d_up_ramp.size() == d_down_ramp.size());
+
+ d_up_phasing.resize(d_up_ramp.size());
+ d_down_phasing.resize(d_down_ramp.size());
+
+ @I_TYPE@ symbol;
+ for(unsigned int i = 0; i < d_up_ramp.size(); i++) {
+ symbol = (i%2 == 0) ? @I_TYPE@(1.0f) : @I_TYPE@(-1.0f);
+ d_up_phasing[i] = symbol * d_up_ramp[i];
+ d_down_phasing[i] = symbol * d_down_ramp[i];
+ }
+
+ //set_relative_rate(1.0);
+ set_tag_propagation_policy(TPP_DONT);
+ }
+
+ @IMPL_NAME@::~@IMPL_NAME@()
+ {
+ }
+
+ void
+ @IMPL_NAME@::forecast(int noutput_items,
+ gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ }
+
+ int
+ @IMPL_NAME@::general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const @I_TYPE@ *in = reinterpret_cast<const @I_TYPE@ *>(input_items[0]);
+ @O_TYPE@ *out = reinterpret_cast<@O_TYPE@ *>(output_items[0]);
+
+ int nwritten = 0;
+ int nread = 0;
+ int nspace = 0;
+ int nskip = 0;
+ int curr_tag_index = 0;
+
+ std::vector<tag_t> length_tags;
+ get_tags_in_window(length_tags, 0, 0, ninput_items[0], d_length_tag_key);
+ std::sort(length_tags.rbegin(), length_tags.rend(), tag_t::offset_compare);
+
+ while((nwritten < noutput_items) && (nread < ninput_items[0])) {
+ if(d_finished) {
+ d_finished = false;
+ break;
+ }
+ nspace = noutput_items - nwritten;
+ switch(d_state) {
+ case(STATE_WAIT):
+ if(!length_tags.empty()) {
+ d_length_tag_offset = length_tags.back().offset;
+ curr_tag_index = (int)(d_length_tag_offset - nitems_read(0));
+ d_ncopy = pmt::to_long(length_tags.back().value);
+ length_tags.pop_back();
+ nskip = curr_tag_index - nread;
+ add_length_tag(nwritten);
+ propagate_tags(curr_tag_index, nwritten, 1, false);
+ enter_prepad();
+ }
+ else {
+ nskip = ninput_items[0] - nread;
+ }
+ if(nskip > 0) {
+ GR_LOG_WARN(d_logger,
+ boost::format("Dropping %1% samples") %
+ nskip);
+ nread += nskip;
+ in += nskip;
+ }
+ break;
+
+ case(STATE_PREPAD):
+ write_padding(out, nwritten, nspace);
+ if(d_index == d_limit)
+ enter_rampup();
+ break;
+
+ case(STATE_RAMPUP):
+ apply_ramp(out, in, nwritten, nread, nspace);
+ if(d_index == d_limit)
+ enter_copy();
+ break;
+
+ case(STATE_COPY):
+ copy_items(out, in, nwritten, nread, nspace);
+ if(d_index == d_limit)
+ enter_rampdown();
+ break;
+
+ case(STATE_RAMPDOWN):
+ apply_ramp(out, in, nwritten, nread, nspace);
+ if(d_index == d_limit)
+ enter_postpad();
+ break;
+
+ case(STATE_POSTPAD):
+ write_padding(out, nwritten, nspace);
+ if(d_index == d_limit)
+ enter_wait();
+ break;
+
+ default:
+ throw std::runtime_error("@BASE_NAME@: invalid state");
+ }
+ }
+
+ consume_each(nread);
+
+ return nwritten;
+ }
+
+ int
+ @IMPL_NAME@::prefix_length() const
+ {
+ return (d_insert_phasing) ?
+ d_nprepad + d_up_ramp.size() : d_nprepad;
+ }
+
+ int
+ @IMPL_NAME@::suffix_length() const
+ {
+ return (d_insert_phasing) ?
+ d_npostpad + d_down_ramp.size() : d_npostpad;
+ }
+
+ void
+ @IMPL_NAME@::write_padding(@O_TYPE@ *&dst, int &nwritten, int nspace)
+ {
+ int nprocess = std::min(d_limit - d_index, nspace);
+ std::memset(dst, 0x00, nprocess * sizeof(@O_TYPE@));
+ dst += nprocess;
+ nwritten += nprocess;
+ d_index += nprocess;
+ }
+
+ void
+ @IMPL_NAME@::copy_items(@O_TYPE@ *&dst, const @I_TYPE@ *&src, int &nwritten,
+ int &nread, int nspace)
+ {
+ int nprocess = std::min(d_limit - d_index, nspace);
+ propagate_tags(nread, nwritten, nprocess);
+ std::memcpy(dst, src, nprocess * sizeof(@O_TYPE@));
+ dst += nprocess;
+ nwritten += nprocess;
+ src += nprocess;
+ nread += nprocess;
+ d_index += nprocess;
+ }
+
+ void
+ @IMPL_NAME@::apply_ramp(@O_TYPE@ *&dst, const @I_TYPE@ *&src, int &nwritten,
+ int &nread, int nspace)
+ {
+ int nprocess = std::min(d_limit - d_index, nspace);
+ @O_TYPE@ *phasing;
+ const @O_TYPE@ *ramp;
+
+ if(d_state == STATE_RAMPUP) {
+ phasing = &d_up_phasing[d_index];
+ ramp = &d_up_ramp[d_index];
+ }
+ else {
+ phasing = &d_down_phasing[d_index];
+ ramp = &d_down_ramp[d_index];
+ }
+
+ if(d_insert_phasing)
+ std::memcpy(dst, phasing, nprocess * sizeof(@O_TYPE@));
+ else {
+ propagate_tags(nread, nwritten, nprocess);
+ VOLK_MULT_@O_TYPE@(dst, src, ramp, nprocess);
+ src += nprocess;
+ nread += nprocess;
+ }
+
+ dst += nprocess;
+ nwritten += nprocess;
+ d_index += nprocess;
+ }
+
+ void
+ @IMPL_NAME@::add_length_tag(int offset)
+ {
+ add_item_tag(0, nitems_written(0) + offset, d_length_tag_key,
+ pmt::from_long(d_ncopy + prefix_length() +
+ suffix_length()),
+ pmt::string_to_symbol(name()));
+ }
+
+ void
+ @IMPL_NAME@::propagate_tags(int in_offset, int out_offset, int count, bool skip)
+ {
+ uint64_t abs_start = nitems_read(0) + in_offset;
+ uint64_t abs_end = abs_start + count;
+ uint64_t abs_offset = nitems_written(0) + out_offset;
+ tag_t temp_tag;
+
+ std::vector<tag_t> tags;
+ std::vector<tag_t>::iterator it;
+
+ get_tags_in_range(tags, 0, abs_start, abs_end);
+
+ for(it = tags.begin(); it != tags.end(); it++) {
+ if(!pmt::equal(it->key, d_length_tag_key)) {
+ if(skip && (it->offset == d_length_tag_offset))
+ continue;
+ temp_tag = *it;
+ temp_tag.offset = abs_offset + it->offset - abs_start;
+ add_item_tag(0, temp_tag);
+ }
+ }
+ }
+
+ void
+ @IMPL_NAME@::enter_wait()
+ {
+ d_finished = true;
+ d_index = 0;
+ d_state = STATE_WAIT;
+ }
+
+ void
+ @IMPL_NAME@::enter_prepad()
+ {
+ d_limit = d_nprepad;
+ d_index = 0;
+ d_state = STATE_PREPAD;
+ }
+
+ void
+ @IMPL_NAME@::enter_rampup()
+ {
+ if(d_insert_phasing)
+ d_limit = d_up_ramp.size();
+ else
+ d_limit = std::min((size_t)(d_ncopy/2), d_up_ramp.size());
+ d_index = 0;
+ d_state = STATE_RAMPUP;
+ }
+
+ void
+ @IMPL_NAME@::enter_copy()
+ {
+ if(d_insert_phasing)
+ d_limit = d_ncopy;
+ else
+ d_limit = d_ncopy - std::min((size_t)((d_ncopy/2)*2),
+ d_up_ramp.size() +
+ d_down_ramp.size());
+ d_index = 0;
+ d_state = STATE_COPY;
+ }
+
+ void
+ @IMPL_NAME@::enter_rampdown()
+ {
+ if(d_insert_phasing)
+ d_limit = d_down_ramp.size();
+ else
+ d_limit = std::min((size_t)(d_ncopy/2), d_down_ramp.size());
+ d_index = 0;
+ d_state = STATE_RAMPDOWN;
+ }
+
+ void
+ @IMPL_NAME@::enter_postpad()
+ {
+ d_limit = d_npostpad;
+ d_index = 0;
+ d_state = STATE_POSTPAD;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/burst_shaper_XX_impl.h.t b/gr-digital/lib/burst_shaper_XX_impl.h.t
new file mode 100644
index 0000000000..99ad7fb08a
--- /dev/null
+++ b/gr-digital/lib/burst_shaper_XX_impl.h.t
@@ -0,0 +1,90 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* @WARNING@ */
+
+#ifndef @GUARD_NAME@
+#define @GUARD_NAME@
+
+#include <gnuradio/digital/@BASE_NAME@.h>
+
+namespace gr {
+ namespace digital {
+
+ class @IMPL_NAME@ : public @BASE_NAME@
+ {
+ protected:
+ enum state_t {STATE_WAIT, STATE_PREPAD, STATE_RAMPUP,
+ STATE_COPY, STATE_RAMPDOWN, STATE_POSTPAD};
+
+ private:
+ const std::vector<@O_TYPE@> d_up_ramp;
+ const std::vector<@O_TYPE@> d_down_ramp;
+ const int d_nprepad;
+ const int d_npostpad;
+ const bool d_insert_phasing;
+ const pmt::pmt_t d_length_tag_key;
+ std::vector<@O_TYPE@> d_up_phasing;
+ std::vector<@O_TYPE@> d_down_phasing;
+ int d_ncopy;
+ int d_limit;
+ int d_index;
+ uint64_t d_length_tag_offset;
+ bool d_finished;
+ state_t d_state;
+
+ void write_padding(@O_TYPE@ *&dst, int &nwritten, int nspace);
+ void copy_items(@O_TYPE@ *&dst, const @I_TYPE@ *&src, int &nwritten,
+ int &nread, int nspace);
+ void apply_ramp(@O_TYPE@ *&dst, const @I_TYPE@ *&src, int &nwritten,
+ int &nread, int nspace);
+ void add_length_tag(int offset);
+ void propagate_tags(int in_offset, int out_offset, int count, bool skip=true);
+ void enter_wait();
+ void enter_prepad();
+ void enter_rampup();
+ void enter_copy();
+ void enter_rampdown();
+ void enter_postpad();
+
+ public:
+ @IMPL_NAME@(const std::vector<@O_TYPE@> &taps, int pre_padding,
+ int post_padding, bool insert_phasing,
+ const std::string &length_tag_name);
+ ~@IMPL_NAME@();
+
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ int pre_padding() const { return d_nprepad; }
+ int post_padding() const { return d_npostpad; }
+ int prefix_length() const;
+ int suffix_length() const;
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* @GUARD_NAME@ */
diff --git a/gr-digital/lib/corr_est_cc_impl.cc b/gr-digital/lib/corr_est_cc_impl.cc
new file mode 100644
index 0000000000..66645f6b5d
--- /dev/null
+++ b/gr-digital/lib/corr_est_cc_impl.cc
@@ -0,0 +1,331 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include <gnuradio/math.h>
+#include "corr_est_cc_impl.h"
+#include <volk/volk.h>
+#include <boost/format.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <gnuradio/filter/pfb_arb_resampler.h>
+#include <gnuradio/filter/firdes.h>
+
+namespace gr {
+ namespace digital {
+
+ corr_est_cc::sptr
+ corr_est_cc::make(const std::vector<gr_complex> &symbols,
+ float sps, unsigned int mark_delay,
+ float threshold)
+ {
+ return gnuradio::get_initial_sptr
+ (new corr_est_cc_impl(symbols, sps, mark_delay, threshold));
+ }
+
+ corr_est_cc_impl::corr_est_cc_impl(const std::vector<gr_complex> &symbols,
+ float sps, unsigned int mark_delay,
+ float threshold)
+ : sync_block("corr_est_cc",
+ io_signature::make(1, 1, sizeof(gr_complex)),
+ io_signature::make(1, 2, sizeof(gr_complex))),
+ d_src_id(pmt::intern(alias()))
+ {
+ d_sps = sps;
+
+ // Create time-reversed conjugate of symbols
+ d_symbols = symbols;
+ for(size_t i=0; i < d_symbols.size(); i++) {
+ d_symbols[i] = conj(d_symbols[i]);
+ }
+ std::reverse(d_symbols.begin(), d_symbols.end());
+
+ set_mark_delay(mark_delay);
+ set_threshold(threshold);
+
+ // Correlation filter
+ d_filter = new kernel::fft_filter_ccc(1, d_symbols);
+
+ // Per comments in gr-filter/include/gnuradio/filter/fft_filter.h,
+ // set the block output multiple to the FFT filter kernel's internal,
+ // assumed "nsamples", to ensure the scheduler always passes a
+ // proper number of samples.
+ int nsamples;
+ nsamples = d_filter->set_taps(d_symbols);
+ set_output_multiple(nsamples);
+
+ // It looks like the kernel::fft_filter_ccc stashes a tail between
+ // calls, so that contains our filtering history (I think). The
+ // fft_filter_ccc block (which calls the kernel::fft_filter_ccc) sets
+ // the history to 1 (0 history items), so let's follow its lead.
+ //set_history(1);
+
+ // We'll (ab)use the history for our own purposes of tagging back in time.
+ // Keep a history of the length of the sync word to delay for tagging.
+ set_history(d_symbols.size()+1);
+
+ declare_sample_delay(1, 0);
+ declare_sample_delay(0, d_symbols.size());
+
+ // Setting the alignment multiple for volk causes problems with the
+ // expected behavior of setting the output multiple for the FFT filter.
+ // Don't set the alignment multiple.
+ //const int alignment_multiple =
+ // volk_get_alignment() / sizeof(gr_complex);
+ //set_alignment(std::max(1,alignment_multiple));
+
+ // In order to easily support the optional second output,
+ // don't deal with an unbounded max number of output items.
+ // For the common case of not using the optional second output,
+ // this ensures we optimally call the volk routines.
+ const size_t nitems = 24*1024;
+ set_max_noutput_items(nitems);
+ d_corr = (gr_complex *)
+ volk_malloc(sizeof(gr_complex)*nitems, volk_get_alignment());
+ d_corr_mag = (float *)
+ volk_malloc(sizeof(float)*nitems, volk_get_alignment());
+ }
+
+ corr_est_cc_impl::~corr_est_cc_impl()
+ {
+ delete d_filter;
+ volk_free(d_corr);
+ volk_free(d_corr_mag);
+ }
+
+ std::vector<gr_complex>
+ corr_est_cc_impl::symbols() const
+ {
+ return d_symbols;
+ }
+
+ void
+ corr_est_cc_impl::set_symbols(const std::vector<gr_complex> &symbols)
+ {
+ gr::thread::scoped_lock lock(d_setlock);
+
+ d_symbols = symbols;
+
+ // Per comments in gr-filter/include/gnuradio/filter/fft_filter.h,
+ // set the block output multiple to the FFT filter kernel's internal,
+ // assumed "nsamples", to ensure the scheduler always passes a
+ // proper number of samples.
+ int nsamples;
+ nsamples = d_filter->set_taps(d_symbols);
+ set_output_multiple(nsamples);
+
+ // It looks like the kernel::fft_filter_ccc stashes a tail between
+ // calls, so that contains our filtering history (I think). The
+ // fft_filter_ccc block (which calls the kernel::fft_filter_ccc) sets
+ // the history to 1 (0 history items), so let's follow its lead.
+ //set_history(1);
+
+ // We'll (ab)use the history for our own purposes of tagging back in time.
+ // Keep a history of the length of the sync word to delay for tagging.
+ set_history(d_symbols.size()+1);
+
+ declare_sample_delay(1, 0);
+ declare_sample_delay(0, d_symbols.size());
+
+ _set_mark_delay(d_stashed_mark_delay);
+ _set_threshold(d_stashed_threshold);
+ }
+
+ unsigned int
+ corr_est_cc_impl::mark_delay() const
+ {
+ return d_mark_delay;
+ }
+
+ void
+ corr_est_cc_impl::_set_mark_delay(unsigned int mark_delay)
+ {
+ d_stashed_mark_delay = mark_delay;
+
+ if(mark_delay >= d_symbols.size()) {
+ d_mark_delay = d_symbols.size()-1;
+ GR_LOG_WARN(d_logger, boost::format("set_mark_delay: asked for %1% but due "
+ "to the symbol size constraints, "
+ "mark delay set to %2%.") \
+ % mark_delay % d_mark_delay);
+ }
+ else {
+ d_mark_delay = mark_delay;
+ }
+ }
+
+ void
+ corr_est_cc_impl::set_mark_delay(unsigned int mark_delay)
+ {
+ gr::thread::scoped_lock lock(d_setlock);
+ _set_mark_delay(mark_delay);
+ }
+
+ float
+ corr_est_cc_impl::threshold() const
+ {
+ return d_thresh;
+ }
+
+ void
+ corr_est_cc_impl::_set_threshold(float threshold)
+ {
+ d_stashed_threshold = threshold;
+
+ // Compute a correlation threshold.
+ // Compute the value of the discrete autocorrelation of the matched
+ // filter with offset 0 (aka the autocorrelation peak).
+ float corr = 0;
+ for(size_t i = 0; i < d_symbols.size(); i++)
+ corr += abs(d_symbols[i]*conj(d_symbols[i]));
+ d_thresh = threshold*corr*corr;
+ }
+
+ void
+ corr_est_cc_impl::set_threshold(float threshold)
+ {
+ gr::thread::scoped_lock lock(d_setlock);
+ _set_threshold(threshold);
+ }
+
+ int
+ corr_est_cc_impl::work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr::thread::scoped_lock lock(d_setlock);
+
+ const gr_complex *in = (gr_complex *)input_items[0];
+ gr_complex *out = (gr_complex*)output_items[0];
+ gr_complex *corr;
+ if (output_items.size() > 1)
+ corr = (gr_complex *) output_items[1];
+ else
+ corr = d_corr;
+
+ // Our correlation filter length
+ unsigned int hist_len = history() - 1;
+
+ // Delay the output by our correlation filter length so we can
+ // tag backwards in time
+ memcpy(out, &in[0], sizeof(gr_complex)*noutput_items);
+
+ // Calculate the correlation of the non-delayed input with the
+ // known symbols.
+ d_filter->filter(noutput_items, &in[hist_len], corr);
+
+ // Find the magnitude squared of the correlation
+ volk_32fc_magnitude_squared_32f(&d_corr_mag[0], corr, noutput_items);
+
+ int isps = (int)(d_sps + 0.5f);
+ int i = 0;
+ while(i < noutput_items) {
+ // Look for the correlator output to cross the threshold
+ if (d_corr_mag[i] <= d_thresh) {
+ i++;
+ continue;
+ }
+ // Go to (just past) the current correlator output peak
+ while ((i < (noutput_items-1)) &&
+ (d_corr_mag[i] < d_corr_mag[i+1]))
+ i++;
+
+ // Delaying the primary signal output by the matched filter
+ // length using history(), means that the the peak output of
+ // the matched filter aligns with the start of the desired
+ // sync word in the primary signal output. This corr_start
+ // tag is not offset to another sample, so that downstream
+ // data-aided blocks (like adaptive equalizers) know exactly
+ // where the start of the correlated symbols are.
+ add_item_tag(0, nitems_written(0) + i, pmt::intern("corr_start"),
+ pmt::from_double(d_corr_mag[i]), d_src_id);
+
+ // Peak detector using a "center of mass" approach center
+ // holds the +/- fraction of a sample index from the found
+ // peak index to the estimated actual peak index.
+ double center = 0.0;
+ if (i > 0 && i < (noutput_items - 1)) {
+ double nom = 0, den = 0;
+ for(int s = 0; s < 3; s++) {
+ nom += (s+1)*d_corr_mag[i+s-1];
+ den += d_corr_mag[i+s-1];
+ }
+ center = nom / den - 2.0;
+ }
+
+ // Calculate the phase offset of the incoming signal.
+ //
+ // The analytic cross-correlation is:
+ //
+ // 2A*e_bb(t-t_d)*exp(-j*2*pi*f*(t-t_d) - j*phi_bb(t-t_d) - j*theta_c)
+ //
+
+ // The analytic auto-correlation's envelope, e_bb(), has its
+ // peak at the "group delay" time, t = t_d. The analytic
+ // cross-correlation's center frequency phase shift, theta_c,
+ // is determined from the argument of the analytic
+ // cross-correlation at the "group delay" time, t = t_d.
+ //
+ // Taking the argument of the analytic cross-correlation at
+ // any other time will include the baseband auto-correlation's
+ // phase term, phi_bb(t-t_d), and a frequency dependent term
+ // of the cross-correlation, which I don't believe maps simply
+ // to expected symbol phase differences.
+ float phase = fast_atan2f(corr[i].imag(), corr[i].real());
+ int index = i + d_mark_delay;
+
+ add_item_tag(0, nitems_written(0) + index, pmt::intern("phase_est"),
+ pmt::from_double(phase), d_src_id);
+ add_item_tag(0, nitems_written(0) + index, pmt::intern("time_est"),
+ pmt::from_double(center), d_src_id);
+ // N.B. the appropriate d_corr_mag[] index is "i", not "index".
+ add_item_tag(0, nitems_written(0) + index, pmt::intern("corr_est"),
+ pmt::from_double(d_corr_mag[i]), d_src_id);
+
+ if (output_items.size() > 1) {
+ // N.B. these debug tags are not offset to avoid walking off out buf
+ add_item_tag(1, nitems_written(0) + i, pmt::intern("phase_est"),
+ pmt::from_double(phase), d_src_id);
+ add_item_tag(1, nitems_written(0) + i, pmt::intern("time_est"),
+ pmt::from_double(center), d_src_id);
+ add_item_tag(1, nitems_written(0) + i, pmt::intern("corr_est"),
+ pmt::from_double(d_corr_mag[i]), d_src_id);
+ }
+
+ // Skip ahead to the next potential symbol peak
+ // (for non-offset/interleaved symbols)
+ i += isps;
+ }
+
+ //if (output_items.size() > 1)
+ // add_item_tag(1, nitems_written(0) + noutput_items - 1,
+ // pmt::intern("ce_eow"), pmt::from_uint64(noutput_items),
+ // d_src_id);
+
+ return noutput_items;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/corr_est_cc_impl.h b/gr-digital/lib/corr_est_cc_impl.h
new file mode 100644
index 0000000000..6e8dd17083
--- /dev/null
+++ b/gr-digital/lib/corr_est_cc_impl.h
@@ -0,0 +1,73 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_CORR_EST_CC_IMPL_H
+#define INCLUDED_DIGITAL_CORR_EST_CC_IMPL_H
+
+#include <gnuradio/digital/corr_est_cc.h>
+#include <gnuradio/filter/fft_filter.h>
+
+using namespace gr::filter;
+
+namespace gr {
+ namespace digital {
+
+ class corr_est_cc_impl : public corr_est_cc
+ {
+ private:
+ pmt::pmt_t d_src_id;
+ std::vector<gr_complex> d_symbols;
+ float d_sps;
+ unsigned int d_mark_delay, d_stashed_mark_delay;
+ float d_thresh, d_stashed_threshold;
+ kernel::fft_filter_ccc *d_filter;
+
+ gr_complex *d_corr;
+ float *d_corr_mag;
+
+ void _set_mark_delay(unsigned int mark_delay);
+ void _set_threshold(float threshold);
+
+ public:
+ corr_est_cc_impl(const std::vector<gr_complex> &symbols,
+ float sps, unsigned int mark_delay,
+ float threshold=0.9);
+ ~corr_est_cc_impl();
+
+ std::vector<gr_complex> symbols() const;
+ void set_symbols(const std::vector<gr_complex> &symbols);
+
+ unsigned int mark_delay() const;
+ void set_mark_delay(unsigned int mark_delay);
+
+ float threshold() const;
+ void set_threshold(float threshold);
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_CORR_EST_CC_IMPL_H */
diff --git a/gr-digital/lib/modulate_vector.cc b/gr-digital/lib/modulate_vector.cc
new file mode 100644
index 0000000000..281e3435c5
--- /dev/null
+++ b/gr-digital/lib/modulate_vector.cc
@@ -0,0 +1,70 @@
+/*
+* Copyright 2015 Free Software Foundation, Inc.
+*
+* This file is part of GNU Radio
+*
+* GNU Radio is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 3, or (at your option)
+* any later version.
+*
+* GNU Radio is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with GNU Radio; see the file COPYING. If not, write to
+* the Free Software Foundation, Inc., 51 Franklin Street,
+* Boston, MA 02110-1301, USA.
+*
+*/
+
+/*
+* Generate a modulated transmit vector corresponding to a particular
+* data sequence, resampling rate, and shaping filter. The output is
+* suitable for use as a candidate filter for the correlate_and_sync
+* block, or just for prototyping.
+*
+* It accepts a sptr to a modulator block as an argument; given
+* suitable data vectors and arguments you should be able to use any of
+* the GNU Radio modulator blocks as a modulator. Be careful that some
+* modulators expect packed words, some expect unpacked words, and some
+* have unique expectations, requirements, or limitations.
+
+* modulator as: gr.block or gr.hier_block
+* taps as: list or array
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/blocks/vector_source_b.h>
+#include <gnuradio/blocks/vector_sink_c.h>
+#include <gnuradio/filter/fir_filter_ccf.h>
+#include <gnuradio/top_block.h>
+#include <gnuradio/digital/modulate_vector.h>
+
+namespace gr {
+ namespace digital {
+ std::vector<gr_complex> modulate_vector_bc(basic_block_sptr modulator,
+ std::vector<uint8_t> data,
+ std::vector<float> taps)
+ {
+ blocks::vector_source_b::sptr vector_src = blocks::vector_source_b::make(data);
+ filter::fir_filter_ccf::sptr filter = filter::fir_filter_ccf::make(1, taps);
+ blocks::vector_sink_c::sptr vector_sink = blocks::vector_sink_c::make();
+
+ top_block_sptr tb = make_top_block("modulate_vector");
+
+ tb->connect(vector_src, 0, modulator, 0);
+ tb->connect(modulator, 0, filter, 0);
+ tb->connect(filter, 0, vector_sink, 0);
+
+ tb->run();
+
+ return vector_sink->data();
+ }
+ } /* namespace digital */
+} /* namespace gr */
diff --git a/gr-digital/lib/msk_timing_recovery_cc_impl.cc b/gr-digital/lib/msk_timing_recovery_cc_impl.cc
new file mode 100644
index 0000000000..4b26573870
--- /dev/null
+++ b/gr-digital/lib/msk_timing_recovery_cc_impl.cc
@@ -0,0 +1,210 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include <gnuradio/math.h>
+#include "msk_timing_recovery_cc_impl.h"
+#include <gnuradio/filter/firdes.h>
+
+namespace gr {
+ namespace digital {
+
+ msk_timing_recovery_cc::sptr
+ msk_timing_recovery_cc::make(float sps, float gain, float limit, int osps=1)
+ {
+ return gnuradio::get_initial_sptr
+ (new msk_timing_recovery_cc_impl(sps, gain, limit, osps));
+ }
+
+ /*
+ * The private constructor
+ */
+ msk_timing_recovery_cc_impl::msk_timing_recovery_cc_impl(float sps, float gain, float limit, int osps)
+ : gr::block("msk_timing_recovery_cc",
+ gr::io_signature::make(1, 1, sizeof(gr_complex)),
+ gr::io_signature::make3(1, 3, sizeof(gr_complex), sizeof(float), sizeof(float))),
+ d_limit(limit),
+ d_interp(new filter::mmse_fir_interpolator_cc()),
+ d_dly_conj_1(0),
+ d_dly_conj_2(0),
+ d_dly_diff_1(0),
+ d_mu(0.5),
+ d_div(0),
+ d_osps(osps)
+ {
+ set_sps(sps);
+ enable_update_rate(true); //fixes tag propagation through variable rate blox
+ set_gain(gain);
+ if(d_osps != 1 && d_osps != 2) throw std::out_of_range("osps must be 1 or 2");
+ }
+
+ msk_timing_recovery_cc_impl::~msk_timing_recovery_cc_impl()
+ {
+ delete d_interp;
+ }
+
+ void msk_timing_recovery_cc_impl::set_sps(float sps) {
+ d_sps = sps/2.0; //loop runs at 2x sps
+ d_omega = d_sps;
+ set_relative_rate(d_osps/sps);
+// set_history(d_sps);
+ }
+
+ float msk_timing_recovery_cc_impl::get_sps(void) {
+ return d_sps;
+ }
+
+ void msk_timing_recovery_cc_impl::set_gain(float gain) {
+ d_gain = gain;
+ if(d_gain <= 0) throw std::out_of_range("Gain must be positive");
+ d_gain_omega = d_gain*d_gain*0.25;
+ }
+
+ float msk_timing_recovery_cc_impl::get_gain(void) {
+ return d_gain;
+ }
+
+ void msk_timing_recovery_cc_impl::set_limit(float limit) {
+ d_limit = limit;
+ }
+
+ float msk_timing_recovery_cc_impl::get_limit(void) {
+ return d_limit;
+ }
+
+ void
+ msk_timing_recovery_cc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ unsigned ninputs = ninput_items_required.size();
+ for(unsigned i=0; i<ninputs; i++) {
+ ninput_items_required[i] = (int)ceil((noutput_items*d_sps*2) + 3.0*d_sps + d_interp->ntaps());
+ }
+ }
+
+ int
+ msk_timing_recovery_cc_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+ float *out2, *out3;
+ if(output_items.size() >= 2) out2 = (float *) output_items[1];
+ if(output_items.size() >= 3) out3 = (float *) output_items[2];
+ int oidx=0, iidx=0;
+ int ninp=ninput_items[0] - 3.0*d_sps;
+ if(ninp <= 0) {
+ consume_each(0);
+ return(0);
+ }
+
+ std::vector<tag_t> tags;
+ get_tags_in_range(tags,
+ 0,
+ nitems_read(0),
+ nitems_read(0)+ninp,
+ pmt::intern("time_est"));
+
+ gr_complex sq, //Squared input
+ dly_conj, //Input delayed sps and conjugated
+ nlin_out, //output of the nonlinearity
+ in_interp; //interpolated input
+ float err_out=0; //error output
+
+ while(oidx < noutput_items && iidx < ninp) {
+ //check to see if there's a tag to reset the timing estimate
+ if(tags.size() > 0) {
+ int offset = tags[0].offset - nitems_read(0);
+ if((offset >= iidx) && (offset < (iidx+d_sps))) {
+ float center = (float) pmt::to_double(tags[0].value);
+ if(center != center) { //test for NaN, it happens somehow
+ tags.erase(tags.begin());
+ goto out;
+ }
+ d_mu = center;
+ iidx = offset;
+ if(d_mu<0) {
+ d_mu++;
+ iidx--;
+ }
+ d_div = 0;
+ d_omega = d_sps;
+ d_dly_conj_2 = d_dly_conj_1;
+ //this keeps the block from outputting an odd number of
+ //samples and throwing off downstream blocks which depend
+ //on proper alignment -- for instance, a decimating FIR
+ //filter.
+// if(d_div == 0 and d_osps == 2) oidx++;
+ tags.erase(tags.begin());
+ }
+ }
+
+out:
+ //the actual equation for the nonlinearity is as follows:
+ //e(n) = in[n]^2 * in[n-sps].conj()^2
+ //we then differentiate the error by subtracting the sample delayed by d_sps/2
+ in_interp = d_interp->interpolate(&in[iidx], d_mu);
+ sq = in_interp*in_interp;
+ //conjugation is distributive.
+ dly_conj = std::conj(d_dly_conj_2*d_dly_conj_2);
+ nlin_out = sq*dly_conj;
+ //TODO: paper argues that some improvement can be had
+ //if you either operate at >2sps or use a better numeric
+ //differentiation method.
+ err_out = std::real(nlin_out - d_dly_diff_1);
+ if(d_div % 2) { //error loop calc once per symbol
+ err_out = gr::branchless_clip(err_out, 3.0);
+ d_omega += d_gain_omega*err_out;
+ d_omega = d_sps + gr::branchless_clip(d_omega-d_sps, d_limit);
+ d_mu += d_gain*err_out;
+ }
+ //output every other d_sps by default.
+ if(!(d_div % 2) || d_osps==2) {
+ out[oidx] = in_interp;
+ if(output_items.size() >= 2) out2[oidx] = err_out;
+ if(output_items.size() >= 3) out3[oidx] = d_mu;
+ oidx++;
+ }
+ d_div++;
+
+ d_dly_conj_1 = in_interp;
+ d_dly_conj_2 = d_dly_conj_1;
+ d_dly_diff_1 = nlin_out;
+
+ //update interpolator twice per symbol
+ d_mu += d_omega;
+ iidx += (int)floor(d_mu);
+ d_mu -= floor(d_mu);
+ }
+
+ consume_each (iidx);
+ return oidx;
+ }
+
+ } /* namespace digital */
+} /* namespace gr */
+
diff --git a/gr-digital/lib/msk_timing_recovery_cc_impl.h b/gr-digital/lib/msk_timing_recovery_cc_impl.h
new file mode 100644
index 0000000000..02c29dc6ec
--- /dev/null
+++ b/gr-digital/lib/msk_timing_recovery_cc_impl.h
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2014 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_IMPL_H
+#define INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_IMPL_H
+
+#include <gnuradio/digital/msk_timing_recovery_cc.h>
+#include <gnuradio/filter/mmse_fir_interpolator_cc.h>
+#include <boost/circular_buffer.hpp>
+#include <gnuradio/filter/fir_filter_with_buffer.h>
+
+namespace gr {
+ namespace digital {
+
+ class msk_timing_recovery_cc_impl : public msk_timing_recovery_cc
+ {
+ private:
+ float d_sps;
+ float d_gain;
+ float d_limit;
+ filter::mmse_fir_interpolator_cc *d_interp;
+ filter::kernel::fir_filter_with_buffer_fff *d_decim;
+ gr_complex d_dly_conj_1, d_dly_conj_2, d_dly_diff_1;
+ float d_mu, d_omega, d_gain_omega;
+ int d_div;
+ int d_osps;
+ int d_loop_rate;
+
+ public:
+ msk_timing_recovery_cc_impl(float sps, float gain, float limit, int osps);
+ ~msk_timing_recovery_cc_impl();
+
+ // Where all the action really happens
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ void set_gain(float gain);
+ float get_gain(void);
+
+ void set_limit(float limit);
+ float get_limit(void);
+
+ void set_sps(float sps);
+ float get_sps(void);
+ };
+ } // namespace digital
+} // namespace gr
+
+#endif /* INCLUDED_DIGITAL_MSK_TIMING_RECOVERY_CC_IMPL_H */
+
diff --git a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc
index 70e840d778..1b0dee4055 100644
--- a/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc
+++ b/gr-digital/lib/ofdm_frame_equalizer_vcvc_impl.cc
@@ -167,7 +167,7 @@ namespace gr {
get_tags_in_window(tags, 0, 0, frame_len);
for (size_t i = 0; i < tags.size(); i++) {
if (tags[i].key != CHAN_TAPS_KEY
- and tags[i].key != pmt::mp(d_length_tag_key_str)) {
+ && tags[i].key != pmt::mp(d_length_tag_key_str)) {
add_item_tag(0, tags[i]);
}
}
diff --git a/gr-digital/python/digital/qa_burst_shaper.py b/gr-digital/python/digital/qa_burst_shaper.py
new file mode 100755
index 0000000000..f85b79ceec
--- /dev/null
+++ b/gr-digital/python/digital/qa_burst_shaper.py
@@ -0,0 +1,340 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+from gnuradio import blocks, digital
+import pmt
+import numpy as np
+import sys
+
+def make_length_tag(offset, length):
+ return gr.python_to_tag({'offset' : offset,
+ 'key' : pmt.intern('packet_len'),
+ 'value' : pmt.from_long(length),
+ 'srcid' : pmt.intern('qa_burst_shaper')})
+
+def make_tag(offset, key, value):
+ return gr.python_to_tag({'offset' : offset,
+ 'key' : pmt.intern(key),
+ 'value' : value,
+ 'srcid' : pmt.intern('qa_burst_shaper')})
+
+def compare_tags(a, b):
+ return a.offset == b.offset and pmt.equal(a.key, b.key) and \
+ pmt.equal(a.value, b.value)
+
+class qa_burst_shaper (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_ff (self):
+ prepad = 10
+ postpad = 10
+ length = 20
+ data = np.ones(length + 10) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5), -4.0*np.ones(5)))
+ tags = (make_length_tag(0, length),)
+ expected = np.concatenate((np.zeros(prepad), window[0:5],
+ np.ones(length - len(window)), window[5:10],
+ np.zeros(postpad)))
+ etag = make_length_tag(0, length + prepad + postpad)
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ self.assertTrue(compare_tags(sink.tags()[0], etag))
+
+ def test_cc (self):
+ prepad = 10
+ postpad = 10
+ length = 20
+ data = np.ones(length + 10,
+ dtype=complex) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5, dtype=complex),
+ -4.0*np.ones(5, dtype=complex)))
+ tags = (make_length_tag(0, length),)
+ expected = np.concatenate((np.zeros(prepad, dtype=complex), window[0:5],
+ np.ones(length - len(window), dtype=complex),
+ window[5:10], np.zeros(postpad,
+ dtype=complex)))
+ etag = make_length_tag(0, length + prepad + postpad)
+
+ # flowgraph
+ source = blocks.vector_source_c(data, tags=tags)
+ shaper = digital.burst_shaper_cc(window, pre_padding=prepad,
+ post_padding=postpad)
+ sink = blocks.vector_sink_c()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertComplexTuplesAlmostEqual(sink.data(), expected, 6)
+ self.assertTrue(compare_tags(sink.tags()[0], etag))
+
+ def test_ff_with_phasing (self):
+ prepad = 10
+ postpad = 10
+ length = 20
+ data = np.ones(length + 10) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5), -4.0*np.ones(5)))
+ tags = (make_length_tag(0, length),)
+ phasing = np.zeros(5)
+ for i in xrange(5):
+ phasing[i] = ((-1.0)**i)
+ expected = np.concatenate((np.zeros(prepad), phasing*window[0:5],
+ np.ones(length), phasing*window[5:10],
+ np.zeros(postpad)))
+ etag = make_length_tag(0, length + prepad + postpad + len(window))
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad,
+ insert_phasing=True)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ self.assertTrue(compare_tags(sink.tags()[0], etag))
+
+ def test_cc_with_phasing (self):
+ prepad = 10
+ postpad = 10
+ length = 20
+ data = np.ones(length + 10,
+ dtype=complex) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5, dtype=complex),
+ -4.0*np.ones(5, dtype=complex)))
+ tags = (make_length_tag(0, length),)
+ phasing = np.zeros(5, dtype=complex)
+ for i in xrange(5):
+ phasing[i] = complex((-1.0)**i)
+ expected = np.concatenate((np.zeros(prepad, dtype=complex),
+ phasing*window[0:5],
+ np.ones(length, dtype=complex),
+ phasing*window[5:10],
+ np.zeros(postpad, dtype=complex)))
+ etag = make_length_tag(0, length + prepad + postpad + len(window))
+
+ # flowgraph
+ source = blocks.vector_source_c(data, tags=tags)
+ shaper = digital.burst_shaper_cc(window, pre_padding=prepad,
+ post_padding=postpad,
+ insert_phasing=True)
+ sink = blocks.vector_sink_c()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertComplexTuplesAlmostEqual(sink.data(), expected, 6)
+ self.assertTrue(compare_tags(sink.tags()[0], etag))
+
+ def test_odd_window (self):
+ prepad = 10
+ postpad = 10
+ length = 20
+ data = np.ones(length + 10) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5), -3.0*np.ones(1),
+ -4.0*np.ones(5)))
+ tags = (make_length_tag(0, length),)
+ expected = np.concatenate((np.zeros(prepad), window[0:6],
+ np.ones(length - len(window) - 1),
+ window[5:11], np.zeros(postpad)))
+ etag = make_length_tag(0, length + prepad + postpad)
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ self.assertTrue(compare_tags(sink.tags()[0], etag))
+
+ def test_short_burst (self):
+ prepad = 10
+ postpad = 10
+ length = 9
+ data = np.ones(length + 10) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5), -3.0*np.ones(1),
+ -4.0*np.ones(5)))
+ tags = (make_length_tag(0, length),)
+ expected = np.concatenate((np.zeros(prepad), window[0:4],
+ np.ones(1), window[5:9],
+ np.zeros(postpad)))
+ etag = make_length_tag(0, length + prepad + postpad)
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ self.assertTrue(compare_tags(sink.tags()[0], etag))
+
+ def test_consecutive_bursts (self):
+ prepad = 10
+ postpad = 10
+ length1 = 15
+ length2 = 25
+ data = np.concatenate((np.ones(length1), -1.0*np.ones(length2),
+ np.zeros(10))) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5), -4.0*np.ones(5)))
+ tags = (make_length_tag(0, length1), make_length_tag(length1, length2))
+ expected = np.concatenate((np.zeros(prepad), window[0:5],
+ np.ones(length1 - len(window)), window[5:10],
+ np.zeros(postpad + prepad), -1.0*window[0:5],
+ -1.0*np.ones(length2 - len(window)),
+ -1.0*window[5:10], np.zeros(postpad)))
+ etags = (make_length_tag(0, length1 + prepad + postpad),
+ make_length_tag(length1 + prepad + postpad,
+ length2 + prepad + postpad))
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ for i in xrange(len(etags)):
+ self.assertTrue(compare_tags(sink.tags()[i], etags[i]))
+
+ def test_tag_gap (self):
+ prepad = 10
+ postpad = 10
+ length = 20
+ gap_len = 5
+ data = np.arange(2*length + 10,
+ dtype=float) # need 10 more to push things through
+ window = np.concatenate((-2.0*np.ones(5), -4.0*np.ones(5)))
+ ewindow = window * np.array([1,-1,1,-1,1,1,-1,1,-1,1],dtype=float)
+ tags = (make_length_tag(0, length),
+ make_length_tag(length + gap_len, length))
+ expected = np.concatenate((np.zeros(prepad), ewindow[0:5],
+ np.arange(0, length, dtype=float),
+ ewindow[5:10], np.zeros(postpad),
+ np.zeros(prepad), ewindow[0:5],
+ np.arange(length + gap_len,
+ 2*length + gap_len, dtype=float),
+ ewindow[5:10], np.zeros(postpad)))
+ burst_len = length + len(window) + prepad + postpad
+ etags = (make_length_tag(0, burst_len),
+ make_length_tag(burst_len, burst_len))
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad,
+ insert_phasing=True)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ for i in xrange(len(etags)):
+ self.assertTrue(compare_tags(sink.tags()[i], etags[i]))
+
+ def test_tag_propagation (self):
+ prepad = 10
+ postpad = 10
+ length1 = 15
+ length2 = 25
+ gap_len = 5
+ lentag1_offset = 0
+ lentag2_offset = length1 + gap_len
+ tag1_offset = 0 # accompanies first length tag
+ tag2_offset = length1 + gap_len # accompanies second length tag
+ tag3_offset = 2 # in ramp-up state
+ tag4_offset = length1 + 2 # in gap; tag will be dropped
+ tag5_offset = length1 + gap_len + 7 # in copy state
+
+ data = np.concatenate((np.ones(length1), np.zeros(gap_len),
+ -1.0*np.ones(length2), np.zeros(10)))
+ window = np.concatenate((-2.0*np.ones(5), -4.0*np.ones(5)))
+ tags = (make_length_tag(lentag1_offset, length1),
+ make_length_tag(lentag2_offset, length2),
+ make_tag(tag1_offset, 'head', pmt.intern('tag1')),
+ make_tag(tag2_offset, 'head', pmt.intern('tag2')),
+ make_tag(tag3_offset, 'body', pmt.intern('tag3')),
+ make_tag(tag4_offset, 'body', pmt.intern('tag4')),
+ make_tag(tag5_offset, 'body', pmt.intern('tag5')))
+ expected = np.concatenate((np.zeros(prepad), window[0:5],
+ np.ones(length1 - len(window)), window[5:10],
+ np.zeros(postpad + prepad), -1.0*window[0:5],
+ -1.0*np.ones(length2 - len(window)),
+ -1.0*window[5:10], np.zeros(postpad)))
+ elentag1_offset = 0
+ elentag2_offset = length1 + prepad + postpad
+ etag1_offset = 0
+ etag2_offset = elentag2_offset
+ etag3_offset = prepad + tag3_offset
+ etag5_offset = 2*prepad + postpad + tag5_offset - gap_len
+ etags = (make_length_tag(elentag1_offset, length1 + prepad + postpad),
+ make_length_tag(elentag2_offset, length2 + prepad + postpad),
+ make_tag(etag1_offset, 'head', pmt.intern('tag1')),
+ make_tag(etag2_offset, 'head', pmt.intern('tag2')),
+ make_tag(etag3_offset, 'body', pmt.intern('tag3')),
+ make_tag(etag5_offset, 'body', pmt.intern('tag5')))
+
+ # flowgraph
+ source = blocks.vector_source_f(data, tags=tags)
+ shaper = digital.burst_shaper_ff(window, pre_padding=prepad,
+ post_padding=postpad)
+ sink = blocks.vector_sink_f()
+ self.tb.connect(source, shaper, sink)
+ self.tb.run ()
+
+ # checks
+ self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6)
+ for x, y in zip(sorted(sink.tags(), key=gr.tag_t_offset_compare_key()),
+ sorted(etags, key=gr.tag_t_offset_compare_key())):
+ self.assertTrue(compare_tags(x, y))
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_burst_shaper, "qa_burst_shaper.xml")
diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i
index 43f68a3d6e..d7a3b81c15 100644
--- a/gr-digital/swig/digital_swig.i
+++ b/gr-digital/swig/digital_swig.i
@@ -1,5 +1,5 @@
/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
+ * Copyright 2011-2015 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -39,6 +39,8 @@
%{
#include "gnuradio/digital/additive_scrambler_bb.h"
#include "gnuradio/digital/binary_slicer_fb.h"
+#include "gnuradio/digital/burst_shaper_cc.h"
+#include "gnuradio/digital/burst_shaper_ff.h"
#include "gnuradio/digital/chunks_to_symbols_bc.h"
#include "gnuradio/digital/chunks_to_symbols_bf.h"
#include "gnuradio/digital/chunks_to_symbols_ic.h"
@@ -52,6 +54,7 @@
#include "gnuradio/digital/constellation_decoder_cb.h"
#include "gnuradio/digital/constellation_receiver_cb.h"
#include "gnuradio/digital/constellation_soft_decoder_cf.h"
+#include "gnuradio/digital/corr_est_cc.h"
#include "gnuradio/digital/correlate_access_code_bb.h"
#include "gnuradio/digital/correlate_access_code_tag_bb.h"
#include "gnuradio/digital/correlate_access_code_bb_ts.h"
@@ -78,9 +81,11 @@
#include "gnuradio/digital/lms_dd_equalizer_cc.h"
#include "gnuradio/digital/map_bb.h"
#include "gnuradio/digital/metric_type.h"
+#include "gnuradio/digital/modulate_vector.h"
#include "gnuradio/digital/mpsk_receiver_cc.h"
#include "gnuradio/digital/mpsk_snr_est.h"
#include "gnuradio/digital/mpsk_snr_est_cc.h"
+#include "gnuradio/digital/msk_timing_recovery_cc.h"
#include "gnuradio/digital/ofdm_carrier_allocator_cvc.h"
#include "gnuradio/digital/ofdm_chanest_vcvc.h"
#include "gnuradio/digital/ofdm_cyclic_prefixer.h"
@@ -115,6 +120,8 @@
%include "gnuradio/digital/additive_scrambler_bb.h"
%include "gnuradio/digital/binary_slicer_fb.h"
+%include "gnuradio/digital/burst_shaper_cc.h"
+%include "gnuradio/digital/burst_shaper_ff.h"
%include "gnuradio/digital/chunks_to_symbols_bc.h"
%include "gnuradio/digital/chunks_to_symbols_bf.h"
%include "gnuradio/digital/chunks_to_symbols_ic.h"
@@ -128,6 +135,7 @@
%include "gnuradio/digital/constellation_decoder_cb.h"
%include "gnuradio/digital/constellation_receiver_cb.h"
%include "gnuradio/digital/constellation_soft_decoder_cf.h"
+%include "gnuradio/digital/corr_est_cc.h"
%include "gnuradio/digital/correlate_access_code_bb.h"
%include "gnuradio/digital/correlate_access_code_tag_bb.h"
%include "gnuradio/digital/correlate_access_code_bb_ts.h"
@@ -154,9 +162,11 @@
%include "gnuradio/digital/lms_dd_equalizer_cc.h"
%include "gnuradio/digital/map_bb.h"
%include "gnuradio/digital/metric_type.h"
+%include "gnuradio/digital/modulate_vector.h"
%include "gnuradio/digital/mpsk_receiver_cc.h"
%include "gnuradio/digital/mpsk_snr_est.h"
%include "gnuradio/digital/mpsk_snr_est_cc.h"
+%include "gnuradio/digital/msk_timing_recovery_cc.h"
%include "gnuradio/digital/ofdm_carrier_allocator_cvc.h"
%include "gnuradio/digital/ofdm_chanest_vcvc.h"
%include "gnuradio/digital/ofdm_cyclic_prefixer.h"
@@ -187,6 +197,8 @@
GR_SWIG_BLOCK_MAGIC2(digital, additive_scrambler_bb);
GR_SWIG_BLOCK_MAGIC2(digital, binary_slicer_fb);
+GR_SWIG_BLOCK_MAGIC2(digital, burst_shaper_cc);
+GR_SWIG_BLOCK_MAGIC2(digital, burst_shaper_ff);
GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bc);
GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_bf);
GR_SWIG_BLOCK_MAGIC2(digital, chunks_to_symbols_ic);
@@ -199,6 +211,7 @@ GR_SWIG_BLOCK_MAGIC2(digital, cma_equalizer_cc);
GR_SWIG_BLOCK_MAGIC2(digital, constellation_decoder_cb);
GR_SWIG_BLOCK_MAGIC2(digital, constellation_receiver_cb);
GR_SWIG_BLOCK_MAGIC2(digital, constellation_soft_decoder_cf);
+GR_SWIG_BLOCK_MAGIC2(digital, corr_est_cc);
GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_bb);
GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_tag_bb);
GR_SWIG_BLOCK_MAGIC2(digital, correlate_access_code_bb_ts);
@@ -224,6 +237,7 @@ GR_SWIG_BLOCK_MAGIC2(digital, lms_dd_equalizer_cc);
GR_SWIG_BLOCK_MAGIC2(digital, map_bb);
GR_SWIG_BLOCK_MAGIC2(digital, mpsk_receiver_cc);
GR_SWIG_BLOCK_MAGIC2(digital, mpsk_snr_est_cc);
+GR_SWIG_BLOCK_MAGIC2(digital, msk_timing_recovery_cc);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_carrier_allocator_cvc);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_chanest_vcvc);
GR_SWIG_BLOCK_MAGIC2(digital, ofdm_cyclic_prefixer);
diff --git a/gr-dtv/examples/README.dvbt b/gr-dtv/examples/README.dvbt
new file mode 100644
index 0000000000..88986c74a8
--- /dev/null
+++ b/gr-dtv/examples/README.dvbt
@@ -0,0 +1,4 @@
+Additional information and links to test streams for the
+DVB-T flow graphs can be found here:
+
+https://github.com/drmpeg/dtv-utils
diff --git a/gr-dtv/examples/dvbt_tx_2k.grc b/gr-dtv/examples/dvbt_tx_2k.grc
new file mode 100644
index 0000000000..3db36aedcf
--- /dev/null
+++ b/gr-dtv/examples/dvbt_tx_2k.grc
@@ -0,0 +1,2076 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.8'?>
+<flow_graph>
+ <timestamp>Thu Jan 16 23:00:58 2014</timestamp>
+ <block>
+ <key>dtv_dvbt_bit_inner_interleaver</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_bit_inner_interleaver_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T2k</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(984, 243)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>(8000000.0 * 8) / 7</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_symbol_inner_interleaver</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_symbol_inner_interleaver_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T2k</value>
+ </param>
+ <param>
+ <key>direction</key>
+ <value>Interleave</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(664, 243)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_const_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_const_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>xmin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>xmax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(360, 555)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_to_stream</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_to_stream_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>2048</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(120, 563)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_energy_dispersal</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_energy_dispersal_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nsize</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(328, 96)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_reed_solomon_enc</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_reed_solomon_enc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>p</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>m</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>gfpoly</key>
+ <value>0x11d</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>255</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>239</value>
+ </param>
+ <param>
+ <key>t</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>s</key>
+ <value>51</value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(512, 43)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_convolutional_interleaver</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_convolutional_interleaver_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>136</value>
+ </param>
+ <param>
+ <key>I</key>
+ <value>12</value>
+ </param>
+ <param>
+ <key>M</key>
+ <value>17</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(736, 75)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_inner_coder</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_inner_coder_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>ninput</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>noutput</key>
+ <value>1512</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>code_rate</key>
+ <value>C2_3</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1000, 67)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_map</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_map_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T2k</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(344, 227)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_vxx</key>
+ <param>
+ <key>id</key>
+ <value>fft_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>2048</value>
+ </param>
+ <param>
+ <key>forward</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value>window.rectangular(2048)</value>
+ </param>
+ <param>
+ <key>shift</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(64, 403)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>/run/shm/advtest.ts</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(112, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_sink</key>
+ <param>
+ <key>id</key>
+ <value>uhd_usrp_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_args</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_chans</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>dev_addr</key>
+ <value>"send_frame_size=65536,num_send_frames=128,master_clock_rate=" + str(samp_rate*4)</value>
+ </param>
+ <param>
+ <key>dev_args</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_rate</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>center_freq0</key>
+ <value>429000000</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>norm_gain0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain2</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain6</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain7</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain8</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain9</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain10</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain31</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>len_tag_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(984, 387)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_cyclic_prefixer</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_cyclic_prefixer_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>input_size</key>
+ <value>2048</value>
+ </param>
+ <param>
+ <key>cp_len</key>
+ <value>64</value>
+ </param>
+ <param>
+ <key>rolloff</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tagname</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 419)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_multiply_const_vxx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_multiply_const_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>const</key>
+ <value>0.0022097087</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(664, 435)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>dvbt_tx_demo</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_reference_signals</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_reference_signals_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>code_rate_hp</key>
+ <value>C2_3</value>
+ </param>
+ <param>
+ <key>code_rate_lp</key>
+ <value>C2_3</value>
+ </param>
+ <param>
+ <key>guard_interval</key>
+ <value>GI_1_32</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T2k</value>
+ </param>
+ <param>
+ <key>include_cell_id</key>
+ <value>cell_ide_no</value>
+ </param>
+ <param>
+ <key>cell_id</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(40, 187)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id>
+ <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_vxx_0</source_block_id>
+ <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_multiply_const_vxx_0</source_block_id>
+ <sink_block_id>uhd_usrp_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_file_source_0</source_block_id>
+ <sink_block_id>dtv_dvbt_energy_dispersal_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_energy_dispersal_0</source_block_id>
+ <sink_block_id>dtv_dvbt_reed_solomon_enc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_convolutional_interleaver_0</source_block_id>
+ <sink_block_id>dtv_dvbt_inner_coder_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_inner_coder_0</source_block_id>
+ <sink_block_id>dtv_dvbt_bit_inner_interleaver_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_bit_inner_interleaver_0</source_block_id>
+ <sink_block_id>dtv_dvbt_symbol_inner_interleaver_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_symbol_inner_interleaver_0</source_block_id>
+ <sink_block_id>dtv_dvbt_map_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_map_0</source_block_id>
+ <sink_block_id>dtv_dvbt_reference_signals_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_reference_signals_0</source_block_id>
+ <sink_block_id>fft_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_reference_signals_0</source_block_id>
+ <sink_block_id>blocks_vector_to_stream_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_to_stream_0</source_block_id>
+ <sink_block_id>qtgui_const_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_reed_solomon_enc_0</source_block_id>
+ <sink_block_id>dtv_dvbt_convolutional_interleaver_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-dtv/examples/dvbt_tx_8k.grc b/gr-dtv/examples/dvbt_tx_8k.grc
new file mode 100644
index 0000000000..4cad688e29
--- /dev/null
+++ b/gr-dtv/examples/dvbt_tx_8k.grc
@@ -0,0 +1,2076 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.8'?>
+<flow_graph>
+ <timestamp>Thu Jan 16 23:00:58 2014</timestamp>
+ <block>
+ <key>qtgui_const_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_const_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>xmin</key>
+ <value>-2</value>
+ </param>
+ <param>
+ <key>xmax</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>style1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>style10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>marker10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(360, 555)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>(8000000.0 * 8) / 7</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_energy_dispersal</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_energy_dispersal_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nsize</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(328, 96)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_reed_solomon_enc</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_reed_solomon_enc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>p</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>m</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>gfpoly</key>
+ <value>0x11d</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>255</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>239</value>
+ </param>
+ <param>
+ <key>t</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>s</key>
+ <value>51</value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(512, 43)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_convolutional_interleaver</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_convolutional_interleaver_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>136</value>
+ </param>
+ <param>
+ <key>I</key>
+ <value>12</value>
+ </param>
+ <param>
+ <key>M</key>
+ <value>17</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(736, 75)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>/run/shm/advtest.ts</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(112, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_sink</key>
+ <param>
+ <key>id</key>
+ <value>uhd_usrp_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_args</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_chans</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>dev_addr</key>
+ <value>"send_frame_size=65536,num_send_frames=128,master_clock_rate=" + str(samp_rate*4)</value>
+ </param>
+ <param>
+ <key>dev_args</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_rate</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>center_freq0</key>
+ <value>429000000</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>50</value>
+ </param>
+ <param>
+ <key>norm_gain0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain2</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain6</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain7</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain8</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain9</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain10</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain31</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>len_tag_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(984, 387)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_multiply_const_vxx</key>
+ <param>
+ <key>id</key>
+ <value>blocks_multiply_const_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>const</key>
+ <value>0.0022097087</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(664, 435)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>dvbt_tx_demo</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_bit_inner_interleaver</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_bit_inner_interleaver_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T8k</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(984, 243)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_symbol_inner_interleaver</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_symbol_inner_interleaver_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T8k</value>
+ </param>
+ <param>
+ <key>direction</key>
+ <value>Interleave</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(664, 243)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_map</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_map_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T8k</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(344, 227)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_reference_signals</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_reference_signals_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>code_rate_hp</key>
+ <value>C2_3</value>
+ </param>
+ <param>
+ <key>code_rate_lp</key>
+ <value>C2_3</value>
+ </param>
+ <param>
+ <key>guard_interval</key>
+ <value>GI_1_32</value>
+ </param>
+ <param>
+ <key>transmission_mode</key>
+ <value>T8k</value>
+ </param>
+ <param>
+ <key>include_cell_id</key>
+ <value>cell_ide_no</value>
+ </param>
+ <param>
+ <key>cell_id</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(40, 187)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_vxx</key>
+ <param>
+ <key>id</key>
+ <value>fft_vxx_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>8192</value>
+ </param>
+ <param>
+ <key>forward</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>window</key>
+ <value>window.rectangular(8192)</value>
+ </param>
+ <param>
+ <key>shift</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(64, 403)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_vector_to_stream</key>
+ <param>
+ <key>id</key>
+ <value>blocks_vector_to_stream_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>8192</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(120, 563)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>digital_ofdm_cyclic_prefixer</key>
+ <param>
+ <key>id</key>
+ <value>digital_ofdm_cyclic_prefixer_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>input_size</key>
+ <value>8192</value>
+ </param>
+ <param>
+ <key>cp_len</key>
+ <value>256</value>
+ </param>
+ <param>
+ <key>rolloff</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tagname</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 419)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_inner_coder</key>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_inner_coder_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>ninput</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>noutput</key>
+ <value>6048</value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>64qam</value>
+ </param>
+ <param>
+ <key>hierarchy</key>
+ <value>nh</value>
+ </param>
+ <param>
+ <key>code_rate</key>
+ <value>C2_3</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1000, 67)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>digital_ofdm_cyclic_prefixer_0</source_block_id>
+ <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_vxx_0</source_block_id>
+ <sink_block_id>digital_ofdm_cyclic_prefixer_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_multiply_const_vxx_0</source_block_id>
+ <sink_block_id>uhd_usrp_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_file_source_0</source_block_id>
+ <sink_block_id>dtv_dvbt_energy_dispersal_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_energy_dispersal_0</source_block_id>
+ <sink_block_id>dtv_dvbt_reed_solomon_enc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_convolutional_interleaver_0</source_block_id>
+ <sink_block_id>dtv_dvbt_inner_coder_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_inner_coder_0</source_block_id>
+ <sink_block_id>dtv_dvbt_bit_inner_interleaver_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_bit_inner_interleaver_0</source_block_id>
+ <sink_block_id>dtv_dvbt_symbol_inner_interleaver_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_symbol_inner_interleaver_0</source_block_id>
+ <sink_block_id>dtv_dvbt_map_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_map_0</source_block_id>
+ <sink_block_id>dtv_dvbt_reference_signals_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_reference_signals_0</source_block_id>
+ <sink_block_id>fft_vxx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_reference_signals_0</source_block_id>
+ <sink_block_id>blocks_vector_to_stream_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_vector_to_stream_0</source_block_id>
+ <sink_block_id>qtgui_const_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbt_reed_solomon_enc_0</source_block_id>
+ <sink_block_id>dtv_dvbt_convolutional_interleaver_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-dtv/grc/CMakeLists.txt b/gr-dtv/grc/CMakeLists.txt
index ce2d71883e..2187e283a5 100644
--- a/gr-dtv/grc/CMakeLists.txt
+++ b/gr-dtv/grc/CMakeLists.txt
@@ -52,6 +52,14 @@ install(FILES
dtv_dvbs2_interleaver_bb.xml
dtv_dvbs2_modulator_bc.xml
dtv_dvbs2_physical_cc.xml
+ dtv_dvbt_energy_dispersal.xml
+ dtv_dvbt_reed_solomon_enc.xml
+ dtv_dvbt_convolutional_interleaver.xml
+ dtv_dvbt_inner_coder.xml
+ dtv_dvbt_bit_inner_interleaver.xml
+ dtv_dvbt_symbol_inner_interleaver.xml
+ dtv_dvbt_map.xml
+ dtv_dvbt_reference_signals.xml
DESTINATION ${GRC_BLOCKS_DIR}
COMPONENT "dtv_python"
)
diff --git a/gr-dtv/grc/dtv_block_tree.xml b/gr-dtv/grc/dtv_block_tree.xml
index 770b7ec0fe..1f05bc75dc 100644
--- a/gr-dtv/grc/dtv_block_tree.xml
+++ b/gr-dtv/grc/dtv_block_tree.xml
@@ -75,5 +75,16 @@
<block>dtv_dvbs2_modulator_bc</block>
<block>dtv_dvbs2_physical_cc</block>
</cat>
+ <cat>
+ <name>DVB-T</name>
+ <block>dtv_dvbt_energy_dispersal</block>
+ <block>dtv_dvbt_reed_solomon_enc</block>
+ <block>dtv_dvbt_convolutional_interleaver</block>
+ <block>dtv_dvbt_inner_coder</block>
+ <block>dtv_dvbt_bit_inner_interleaver</block>
+ <block>dtv_dvbt_symbol_inner_interleaver</block>
+ <block>dtv_dvbt_map</block>
+ <block>dtv_dvbt_reference_signals</block>
+ </cat>
</cat>
</cat>
diff --git a/gr-dtv/grc/dtv_dvbt_bit_inner_interleaver.xml b/gr-dtv/grc/dtv_dvbt_bit_inner_interleaver.xml
new file mode 100644
index 0000000000..31f1c2cfa5
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_bit_inner_interleaver.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Bit Inner Interleaver
+###################################################
+ -->
+<block>
+ <name>Bit Inner Interleaver</name>
+ <key>dtv_dvbt_bit_inner_interleaver</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_bit_inner_interleaver($transmission_mode.payload_length, $constellation.val, $hierarchy.val, $transmission_mode.val)</make>
+ <param>
+ <name>Constellation Type</name>
+ <key>constellation</key>
+ <type>enum</type>
+ <option>
+ <name>QPSK</name>
+ <key>qpsk</key>
+ <opt>val:dtv.MOD_QPSK</opt>
+ </option>
+ <option>
+ <name>16QAM</name>
+ <key>16qam</key>
+ <opt>val:dtv.MOD_16QAM</opt>
+ </option>
+ <option>
+ <name>64QAM</name>
+ <key>64qam</key>
+ <opt>val:dtv.MOD_64QAM</opt>
+ </option>
+ </param>
+ <param>
+ <name>Hierarchy Type</name>
+ <key>hierarchy</key>
+ <type>enum</type>
+ <option>
+ <name>Non Hierarchical</name>
+ <key>nh</key>
+ <opt>val:dtv.NH</opt>
+ <opt>num_streams:1</opt>
+ </option>
+ <option>
+ <name>Alpha 1</name>
+ <key>alpha1</key>
+ <opt>val:dtv.ALPHA1</opt>
+ <opt>num_streams:2</opt>
+ </option>
+ <option>
+ <name>Alpha 2</name>
+ <key>alpha2</key>
+ <opt>val:dtv.ALPHA2</opt>
+ <opt>num_streams:2</opt>
+ </option>
+ <option>
+ <name>Alpha 4</name>
+ <key>alpha4</key>
+ <opt>val:dtv.ALPHA4</opt>
+ <opt>num_streams:2</opt>
+ </option>
+ </param>
+ <param>
+ <name>Transmission Mode</name>
+ <key>transmission_mode</key>
+ <type>enum</type>
+ <option>
+ <name>2K</name>
+ <key>T2k</key>
+ <opt>val:dtv.T2k</opt>
+ <opt>payload_length:1512</opt>
+ </option>
+ <option>
+ <name>8K</name>
+ <key>T8k</key>
+ <opt>val:dtv.T8k</opt>
+ <opt>payload_length:6048</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ <nports>$hierarchy.num_streams</nports>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_convolutional_interleaver.xml b/gr-dtv/grc/dtv_dvbt_convolutional_interleaver.xml
new file mode 100644
index 0000000000..04518dd622
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_convolutional_interleaver.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Convolutional Interleaver
+###################################################
+ -->
+<block>
+ <name>Convolutional Interleaver</name>
+ <key>dtv_dvbt_convolutional_interleaver</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_convolutional_interleaver($blocks, $I, $M)</make>
+ <param>
+ <name>Blocks (12 Bytes)</name>
+ <key>blocks</key>
+ <value>136</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Number of Shift registers</name>
+ <key>I</key>
+ <value>12</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Depth of shift registers</name>
+ <key>M</key>
+ <value>17</value>
+ <type>int</type>
+ </param>
+ <check>$blocks &gt; 0</check>
+ <check>$I &gt; 0</check>
+ <check>$M &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$blocks*$I</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>1</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_energy_dispersal.xml b/gr-dtv/grc/dtv_dvbt_energy_dispersal.xml
new file mode 100644
index 0000000000..50746c8e4d
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_energy_dispersal.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Energy Dispersal
+###################################################
+ -->
+<block>
+ <name>Energy Dispersal</name>
+ <key>dtv_dvbt_energy_dispersal</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_energy_dispersal($nsize)</make>
+ <param>
+ <name>Blocks(1504 Bytes)</name>
+ <key>nsize</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <check>$nsize &gt; 0</check>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>1</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>1504*$nsize</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_inner_coder.xml b/gr-dtv/grc/dtv_dvbt_inner_coder.xml
new file mode 100644
index 0000000000..4751065dd1
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_inner_coder.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Inner Coder
+###################################################
+ -->
+<block>
+ <name>Inner Coder</name>
+ <key>dtv_dvbt_inner_coder</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_inner_coder($ninput, $noutput, $constellation.val, $hierarchy.val, $code_rate.val)</make>
+ <param>
+ <name>Input length</name>
+ <key>ninput</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Output length</name>
+ <key>noutput</key>
+ <value>1512</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Constellation Type</name>
+ <key>constellation</key>
+ <type>enum</type>
+ <option>
+ <name>QPSK</name>
+ <key>qpsk</key>
+ <opt>val:dtv.MOD_QPSK</opt>
+ </option>
+ <option>
+ <name>16QAM</name>
+ <key>16qam</key>
+ <opt>val:dtv.MOD_16QAM</opt>
+ </option>
+ <option>
+ <name>64QAM</name>
+ <key>64qam</key>
+ <opt>val:dtv.MOD_64QAM</opt>
+ </option>
+ </param>
+ <param>
+ <name>Hierarchy Type</name>
+ <key>hierarchy</key>
+ <type>enum</type>
+ <option>
+ <name>Non Hierarchical</name>
+ <key>nh</key>
+ <opt>val:dtv.NH</opt>
+ </option>
+ <option>
+ <name>Alpha 1</name>
+ <key>alpha1</key>
+ <opt>val:dtv.ALPHA1</opt>
+ </option>
+ <option>
+ <name>Alpha 2</name>
+ <key>alpha2</key>
+ <opt>val:dtv.ALPHA2</opt>
+ </option>
+ <option>
+ <name>Alpha 4</name>
+ <key>alpha4</key>
+ <opt>val:dtv.ALPHA4</opt>
+ </option>
+ </param>
+ <param>
+ <name>Code rate</name>
+ <key>code_rate</key>
+ <type>enum</type>
+ <option>
+ <name>1/2</name>
+ <key>C1_2</key>
+ <opt>val:dtv.C1_2</opt>
+ </option>
+ <option>
+ <name>2/3</name>
+ <key>C2_3</key>
+ <opt>val:dtv.C2_3</opt>
+ </option>
+ <option>
+ <name>3/4</name>
+ <key>C3_4</key>
+ <opt>val:dtv.C3_4</opt>
+ </option>
+ <option>
+ <name>5/6</name>
+ <key>C5_6</key>
+ <opt>val:dtv.C5_6</opt>
+ </option>
+ <option>
+ <name>7/8</name>
+ <key>C7_8</key>
+ <opt>val:dtv.C7_8</opt>
+ </option>
+ </param>
+ <check>$ninput &gt; 0</check>
+ <check>$noutput &gt; 0</check>
+ <check>$noutput &gt;= $ninput</check>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$ninput</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>$noutput</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_map.xml b/gr-dtv/grc/dtv_dvbt_map.xml
new file mode 100644
index 0000000000..705a508033
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_map.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Map
+###################################################
+ -->
+<block>
+ <name>DVB-T Map</name>
+ <key>dtv_dvbt_map</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_map($transmission_mode.payload_length, $constellation.val, $hierarchy.val, $transmission_mode.val, $gain)</make>
+ <param>
+ <name>Constellation Type</name>
+ <key>constellation</key>
+ <type>enum</type>
+ <option>
+ <name>QPSK</name>
+ <key>qpsk</key>
+ <opt>val:dtv.MOD_QPSK</opt>
+ </option>
+ <option>
+ <name>16QAM</name>
+ <key>16qam</key>
+ <opt>val:dtv.MOD_16QAM</opt>
+ </option>
+ <option>
+ <name>64QAM</name>
+ <key>64qam</key>
+ <opt>val:dtv.MOD_64QAM</opt>
+ </option>
+ </param>
+ <param>
+ <name>Hierarchy Type</name>
+ <key>hierarchy</key>
+ <type>enum</type>
+ <option>
+ <name>Non Hierarchical</name>
+ <key>nh</key>
+ <opt>val:dtv.NH</opt>
+ </option>
+ <option>
+ <name>Alpha 1</name>
+ <key>alpha1</key>
+ <opt>val:dtv.ALPHA1</opt>
+ </option>
+ <option>
+ <name>Alpha 2</name>
+ <key>alpha2</key>
+ <opt>val:dtv.ALPHA2</opt>
+ </option>
+ <option>
+ <name>Alpha 4</name>
+ <key>alpha4</key>
+ <opt>val:dtv.ALPHA4</opt>
+ </option>
+ </param>
+ <param>
+ <name>Transmission Mode</name>
+ <key>transmission_mode</key>
+ <type>enum</type>
+ <option>
+ <name>2K</name>
+ <key>T2k</key>
+ <opt>val:dtv.T2k</opt>
+ <opt>payload_length:1512</opt>
+ </option>
+ <option>
+ <name>8K</name>
+ <key>T8k</key>
+ <opt>val:dtv.T8k</opt>
+ <opt>payload_length:6048</opt>
+ </option>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1</value>
+ <type>complex</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_reed_solomon_enc.xml b/gr-dtv/grc/dtv_dvbt_reed_solomon_enc.xml
new file mode 100644
index 0000000000..3dd57a7df0
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_reed_solomon_enc.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Reed Solomon Encoder
+###################################################
+ -->
+<block>
+ <name>Reed-Solomon Encoder</name>
+ <key>dtv_dvbt_reed_solomon_enc</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_reed_solomon_enc($p, $m, $gfpoly, $n, $k, $t, $s, $blocks)</make>
+ <param>
+ <name>p</name>
+ <key>p</key>
+ <value>2</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>m</name>
+ <key>m</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>GF polynomial</name>
+ <key>gfpoly</key>
+ <value>0x11d</value>
+ <type>raw</type>
+ </param>
+ <param>
+ <name>N</name>
+ <key>n</key>
+ <value>255</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>K</name>
+ <key>k</key>
+ <value>239</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>t</name>
+ <key>t</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Shortening size</name>
+ <key>s</key>
+ <value>51</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Blocks</name>
+ <key>blocks</key>
+ <value>8</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$blocks*($k-$s)</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>$blocks*($n-$s)</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_reference_signals.xml b/gr-dtv/grc/dtv_dvbt_reference_signals.xml
new file mode 100644
index 0000000000..9be57630e5
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_reference_signals.xml
@@ -0,0 +1,222 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Reference Signals
+###################################################
+ -->
+<block>
+ <name>Reference Signals</name>
+ <key>dtv_dvbt_reference_signals</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_reference_signals($type.size, $transmission_mode.payload_length, $transmission_mode.fft_length, $constellation.val, $hierarchy.val, $code_rate_hp.val, $code_rate_lp.val, $guard_interval.val, $transmission_mode.val, $include_cell_id.val, $cell_id)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Constellation Type</name>
+ <key>constellation</key>
+ <type>enum</type>
+ <option>
+ <name>QPSK</name>
+ <key>qpsk</key>
+ <opt>val:dtv.MOD_QPSK</opt>
+ </option>
+ <option>
+ <name>16QAM</name>
+ <key>16qam</key>
+ <opt>val:dtv.MOD_16QAM</opt>
+ </option>
+ <option>
+ <name>64QAM</name>
+ <key>64qam</key>
+ <opt>val:dtv.MOD_64QAM</opt>
+ </option>
+ </param>
+ <param>
+ <name>Hierarchy Type</name>
+ <key>hierarchy</key>
+ <type>enum</type>
+ <option>
+ <name>Non Hierarchical</name>
+ <key>nh</key>
+ <opt>val:dtv.NH</opt>
+ </option>
+ <option>
+ <name>Alpha 1</name>
+ <key>alpha1</key>
+ <opt>val:dtv.ALPHA1</opt>
+ </option>
+ <option>
+ <name>Alpha 2</name>
+ <key>alpha2</key>
+ <opt>val:dtv.ALPHA2</opt>
+ </option>
+ <option>
+ <name>Alpha 4</name>
+ <key>alpha4</key>
+ <opt>val:dtv.ALPHA4</opt>
+ </option>
+ </param>
+ <param>
+ <name>Code rate HP</name>
+ <key>code_rate_hp</key>
+ <type>enum</type>
+ <option>
+ <name>1/2</name>
+ <key>C1_2</key>
+ <opt>val:dtv.C1_2</opt>
+ </option>
+ <option>
+ <name>2/3</name>
+ <key>C2_3</key>
+ <opt>val:dtv.C2_3</opt>
+ </option>
+ <option>
+ <name>3/4</name>
+ <key>C3_4</key>
+ <opt>val:dtv.C3_4</opt>
+ </option>
+ <option>
+ <name>5/6</name>
+ <key>C5_6</key>
+ <opt>val:dtv.C5_6</opt>
+ </option>
+ <option>
+ <name>7/8</name>
+ <key>C7_8</key>
+ <opt>val:dtv.C7_8</opt>
+ </option>
+ </param>
+ <param>
+ <name>Code rate LP</name>
+ <key>code_rate_lp</key>
+ <type>enum</type>
+ <option>
+ <name>1/2</name>
+ <key>C1_2</key>
+ <opt>val:dtv.C1_2</opt>
+ </option>
+ <option>
+ <name>2/3</name>
+ <key>C2_3</key>
+ <opt>val:dtv.C2_3</opt>
+ </option>
+ <option>
+ <name>3/4</name>
+ <key>C3_4</key>
+ <opt>val:dtv.C3_4</opt>
+ </option>
+ <option>
+ <name>5/6</name>
+ <key>C5_6</key>
+ <opt>val:dtv.C5_6</opt>
+ </option>
+ <option>
+ <name>7/8</name>
+ <key>C7_8</key>
+ <opt>val:dtv.C7_8</opt>
+ </option>
+ </param>
+ <param>
+ <name>Guard Interval</name>
+ <key>guard_interval</key>
+ <type>enum</type>
+ <option>
+ <name>1/32</name>
+ <key>GI_1_32</key>
+ <opt>val:dtv.GI_1_32</opt>
+ </option>
+ <option>
+ <name>1/16</name>
+ <key>GI_1_16</key>
+ <opt>val:dtv.GI_1_16</opt>
+ </option>
+ <option>
+ <name>1/8</name>
+ <key>GI_1_8</key>
+ <opt>val:dtv.GI_1_8</opt>
+ </option>
+ <option>
+ <name>1/4</name>
+ <key>GI_1_4</key>
+ <opt>val:dtv.GI_1_4</opt>
+ </option>
+ </param>
+ <param>
+ <name>Transmission Mode</name>
+ <key>transmission_mode</key>
+ <type>enum</type>
+ <option>
+ <name>2K</name>
+ <key>T2k</key>
+ <opt>val:dtv.T2k</opt>
+ <opt>fft_length:2048</opt>
+ <opt>payload_length:1512</opt>
+ </option>
+ <option>
+ <name>8K</name>
+ <key>T8k</key>
+ <opt>val:dtv.T8k</opt>
+ <opt>fft_length:8192</opt>
+ <opt>payload_length:6048</opt>
+ </option>
+ </param>
+ <param>
+ <name>Include Cell ID</name>
+ <key>include_cell_id</key>
+ <type>enum</type>
+ <option>
+ <name>Yes</name>
+ <key>call_id_yes</key>
+ <opt>val:1</opt>
+ </option>
+ <option>
+ <name>No</name>
+ <key>cell_ide_no</key>
+ <opt>val:0</opt>
+ </option>
+ </param>
+ <param>
+ <name>Cell Id</name>
+ <key>cell_id</key>
+ <value>0</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>complex</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>complex</type>
+ <vlen>$transmission_mode.fft_length</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbt_symbol_inner_interleaver.xml b/gr-dtv/grc/dtv_dvbt_symbol_inner_interleaver.xml
new file mode 100644
index 0000000000..f440769a46
--- /dev/null
+++ b/gr-dtv/grc/dtv_dvbt_symbol_inner_interleaver.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## DVB-T Symbol Inner Interleaver
+###################################################
+ -->
+<block>
+ <name>Symbol Inner Interleaver</name>
+ <key>dtv_dvbt_symbol_inner_interleaver</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.dvbt_symbol_inner_interleaver($transmission_mode.payload_length, $transmission_mode.val, $direction.val)</make>
+ <param>
+ <name>Transmission Mode</name>
+ <key>transmission_mode</key>
+ <type>enum</type>
+ <option>
+ <name>2K</name>
+ <key>T2k</key>
+ <opt>val:dtv.T2k</opt>
+ <opt>fft_length:2048</opt>
+ <opt>payload_length:1512</opt>
+ </option>
+ <option>
+ <name>8K</name>
+ <key>T8k</key>
+ <opt>val:dtv.T8k</opt>
+ <opt>fft_length:8192</opt>
+ <opt>payload_length:6048</opt>
+ </option>
+ </param>
+ <param>
+ <name>Direction</name>
+ <key>direction</key>
+ <type>enum</type>
+ <option>
+ <name>Interleave</name>
+ <key>Interleave</key>
+ <opt>val:1</opt>
+ </option>
+ <option>
+ <name>Deinterleave</name>
+ <key>Deinterleave</key>
+ <opt>val:0</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ <vlen>$transmission_mode.payload_length</vlen>
+ </source>
+</block>
diff --git a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
index 97264492cb..d1eff3f891 100644
--- a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
+++ b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
@@ -39,6 +39,7 @@ install(FILES
atsc_trellis_encoder.h
atsc_field_sync_mux.h
dvb_config.h
+ dvbt_config.h
dvbs2_config.h
dvbt2_config.h
dvb_bbheader_bb.h
@@ -57,6 +58,14 @@ install(FILES
dvbs2_interleaver_bb.h
dvbs2_modulator_bc.h
dvbs2_physical_cc.h
+ dvbt_energy_dispersal.h
+ dvbt_reed_solomon_enc.h
+ dvbt_convolutional_interleaver.h
+ dvbt_inner_coder.h
+ dvbt_bit_inner_interleaver.h
+ dvbt_symbol_inner_interleaver.h
+ dvbt_map.h
+ dvbt_reference_signals.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/dtv
COMPONENT "dtv_devel"
)
diff --git a/gr-dtv/include/gnuradio/dtv/dvb_config.h b/gr-dtv/include/gnuradio/dtv/dvb_config.h
index d08c9c882e..9405f966b0 100644
--- a/gr-dtv/include/gnuradio/dtv/dvb_config.h
+++ b/gr-dtv/include/gnuradio/dtv/dvb_config.h
@@ -38,6 +38,7 @@ namespace gr {
C3_4,
C4_5,
C5_6,
+ C7_8,
C8_9,
C9_10,
C13_45,
@@ -97,6 +98,16 @@ namespace gr {
MOD_OTHER,
};
+ enum dvb_guardinterval_t {
+ GI_1_32 = 0,
+ GI_1_16,
+ GI_1_8,
+ GI_1_4,
+ GI_1_128,
+ GI_19_128,
+ GI_19_256,
+ };
+
} // namespace dtv
} // namespace gr
@@ -104,6 +115,7 @@ typedef gr::dtv::dvb_standard_t dvb_standard_t;
typedef gr::dtv::dvb_code_rate_t dvb_code_rate_t;
typedef gr::dtv::dvb_framesize_t dvb_framesize_t;
typedef gr::dtv::dvb_constellation_t dvb_constellation_t;
+typedef gr::dtv::dvb_guardinterval_t dvb_guardinterval_t;
#endif /* INCLUDED_DTV_DVB_CONFIG_H */
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_config.h b/gr-dtv/include/gnuradio/dtv/dvbt2_config.h
index 928690c3a0..906d953255 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_config.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_config.h
@@ -64,16 +64,6 @@ namespace gr {
FFTSIZE_16K_T2GI = 11,
};
- enum dvbt2_guardinterval_t {
- GI_1_32 = 0,
- GI_1_16,
- GI_1_8,
- GI_1_4,
- GI_1_128,
- GI_19_128,
- GI_19_256,
- };
-
enum dvbt2_papr_t {
PAPR_OFF = 0,
PAPR_ACE,
@@ -153,7 +143,6 @@ typedef gr::dtv::dvbt2_inputmode_t dvbt2_inputmode_t;
typedef gr::dtv::dvbt2_extended_carrier_t dvbt2_extended_carrier_t;
typedef gr::dtv::dvbt2_preamble_t dvbt2_preamble_t;
typedef gr::dtv::dvbt2_fftsize_t dvbt2_fftsize_t;
-typedef gr::dtv::dvbt2_guardinterval_t dvbt2_guardinterval_t;
typedef gr::dtv::dvbt2_papr_t dvbt2_papr_t;
typedef gr::dtv::dvbt2_l1constellation_t dvbt2_l1constellation_t;
typedef gr::dtv::dvbt2_pilotpattern_t dvbt2_pilotpattern_t;
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_framemapper_cc.h b/gr-dtv/include/gnuradio/dtv/dvbt2_framemapper_cc.h
index abead6adbb..bf6e4db297 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_framemapper_cc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_framemapper_cc.h
@@ -65,7 +65,7 @@ namespace gr {
* \param l1scrambled scramble L1 post signalling (on or off).
* \param inband In-band type B signalling (on or off).
*/
- static sptr make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband);
+ static sptr make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband);
};
} // namespace dtv
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_freqinterleaver_cc.h b/gr-dtv/include/gnuradio/dtv/dvbt2_freqinterleaver_cc.h
index cfb352b109..766fe031a3 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_freqinterleaver_cc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_freqinterleaver_cc.h
@@ -22,6 +22,7 @@
#define INCLUDED_DTV_DVBT2_FREQINTERLEAVER_CC_H
#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
#include <gnuradio/dtv/dvbt2_config.h>
#include <gnuradio/sync_block.h>
@@ -52,7 +53,7 @@ namespace gr {
* \param version DVB-T2 specification version.
* \param preamble P1 symbol preamble format.
*/
- static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble);
+ static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble);
};
} // namespace dtv
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_miso_cc.h b/gr-dtv/include/gnuradio/dtv/dvbt2_miso_cc.h
index 1268ae8dae..c16e711e9b 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_miso_cc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_miso_cc.h
@@ -22,6 +22,7 @@
#define INCLUDED_DTV_DVBT2_MISO_CC_H
#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
#include <gnuradio/dtv/dvbt2_config.h>
#include <gnuradio/sync_block.h>
@@ -51,7 +52,7 @@ namespace gr {
* \param numdatasyms number of OFDM symbols in a T2 frame.
* \param paprmode PAPR reduction mode.
*/
- static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode);
+ static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode);
};
} // namespace dtv
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_p1insertion_cc.h b/gr-dtv/include/gnuradio/dtv/dvbt2_p1insertion_cc.h
index dd15026cb3..84e0d4a268 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_p1insertion_cc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_p1insertion_cc.h
@@ -22,6 +22,7 @@
#define INCLUDED_DTV_DVBT2_P1INSERTION_CC_H
#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
#include <gnuradio/dtv/dvbt2_config.h>
#include <gnuradio/block.h>
@@ -51,7 +52,7 @@ namespace gr {
* \param showlevels print peak IQ levels.
* \param vclip set peak IQ level threshold.
*/
- static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip);
+ static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip);
};
} // namespace dtv
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_paprtr_cc.h b/gr-dtv/include/gnuradio/dtv/dvbt2_paprtr_cc.h
index 728a6650a2..5a39dfa565 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_paprtr_cc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_paprtr_cc.h
@@ -22,6 +22,7 @@
#define INCLUDED_DTV_DVBT2_PAPRTR_CC_H
#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
#include <gnuradio/dtv/dvbt2_config.h>
#include <gnuradio/sync_block.h>
@@ -54,7 +55,7 @@ namespace gr {
* \param iterations PAPR algorithm number of iterations.
* \param vlength input and output vector length.
*/
- static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength);
+ static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength);
};
} // namespace dtv
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt2_pilotgenerator_cc.h b/gr-dtv/include/gnuradio/dtv/dvbt2_pilotgenerator_cc.h
index f74005a84a..19ae6d948f 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbt2_pilotgenerator_cc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbt2_pilotgenerator_cc.h
@@ -22,6 +22,7 @@
#define INCLUDED_DTV_DVBT2_PILOTGENERATOR_CC_H
#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
#include <gnuradio/dtv/dvbt2_config.h>
#include <gnuradio/block.h>
@@ -56,7 +57,7 @@ namespace gr {
* \param bandwidth sin(x)/x equalization bandwidth.
* \param vlength output vector length.
*/
- static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength);
+ static sptr make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength);
};
} // namespace dtv
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_interleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_interleaver.h
new file mode 100644
index 0000000000..d74763e5eb
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_bit_inner_interleaver.h
@@ -0,0 +1,67 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_BIT_INNER_INTERLEAVER_H
+#define INCLUDED_DTV_DVBT_BIT_INNER_INTERLEAVER_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+#include <gnuradio/dtv/dvb_config.h>
+#include <gnuradio/dtv/dvbt_config.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Bit Inner interleaver.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.3.4.1 \n
+ * Data Input format: \n
+ * 000000X0X1 - QPSK. \n
+ * 0000X0X1X2X3 - 16QAM. \n
+ * 00X0X1X2X3X4X5 - 64QAM. \n
+ * Data Output format: \n
+ * 000000B0B1 - QPSK. \n
+ * 0000B0B1B2B3 - 16QAM. \n
+ * 00B0B1B2B3B4B5 - 64QAM. \n
+ * bit interleaver block size is 126.
+ */
+ class DTV_API dvbt_bit_inner_interleaver : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_bit_inner_interleaver> sptr;
+
+ /*!
+ * \brief Create a Bit Inner interleaver
+ *
+ * \param nsize length of input stream. \n
+ * \param constellation constellation used. \n
+ * \param hierarchy hierarchy used. \n
+ * \param transmission transmission mode used.
+ */
+ static sptr make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_BIT_INNER_INTERLEAVER_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_config.h b/gr-dtv/include/gnuradio/dtv/dvbt_config.h
new file mode 100644
index 0000000000..c6bfa1a7e5
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_config.h
@@ -0,0 +1,45 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_CONFIG_H
+#define INCLUDED_DTV_DVBT_CONFIG_H
+
+namespace gr {
+ namespace dtv {
+ enum dvbt_hierarchy_t {
+ NH = 0,
+ ALPHA1,
+ ALPHA2,
+ ALPHA4,
+ };
+
+ enum dvbt_transmission_mode_t {
+ T2k = 0,
+ T8k = 1,
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+typedef gr::dtv::dvbt_hierarchy_t dvbt_hierarchy_t;
+typedef gr::dtv::dvbt_transmission_mode_t dvbt_transmission_mode_t;
+
+#endif /* INCLUDED_DTV_DVBT_CONFIG_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_interleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_interleaver.h
new file mode 100644
index 0000000000..a4c9577b54
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_convolutional_interleaver.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_CONVOLUTIONAL_INTERLEAVER_H
+#define INCLUDED_DTV_DVBT_CONVOLUTIONAL_INTERLEAVER_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/sync_interpolator.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Convolutional interleaver.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.3.1 \n
+ * Forney (Ramsey type III) convolutional interleaver. \n
+ * Input: Blocks of I bytes size. \n
+ * Output: Stream of 1 byte elements.
+ */
+ class DTV_API dvbt_convolutional_interleaver : virtual public sync_interpolator
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_convolutional_interleaver> sptr;
+
+ /*!
+ * \brief Create a DVB-T convolutional interleaver.
+ *
+ * \param nsize number of blocks to process. \n
+ * \param I size of a block. \n
+ * \param M depth length for each element in shift registers.
+ */
+ static sptr make(int nsize, int I, int M);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_CONVOLUTIONAL_INTERLEAVER_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_energy_dispersal.h b/gr-dtv/include/gnuradio/dtv/dvbt_energy_dispersal.h
new file mode 100644
index 0000000000..b5258bbe1d
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_energy_dispersal.h
@@ -0,0 +1,58 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_ENERGY_DISPERSAL_H
+#define INCLUDED_DTV_DVBT_ENERGY_DISPERSAL_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Energy dispersal.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 - Clause 4.3.1 \n
+ * Input - MPEG-2 transport packets (including sync - 0x47). \n
+ * Output - Randomized MPEG-2 transport packets. \n
+ * If first byte is not a SYNC then look for it. \n
+ * First sync in a row of 8 packets is reversed - 0xB8. \n
+ * Block size is 188 bytes.
+ */
+ class DTV_API dvbt_energy_dispersal : virtual public gr::block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_energy_dispersal> sptr;
+
+ /*!
+ * \brief Create DVB-T energy dispersal.
+ *
+ * \param nsize number of blocks.
+ */
+ static sptr make(int nsize);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_ENERGY_DISPERSAL_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_inner_coder.h b/gr-dtv/include/gnuradio/dtv/dvbt_inner_coder.h
new file mode 100644
index 0000000000..e88596e09b
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_inner_coder.h
@@ -0,0 +1,69 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_INNER_CODER_H
+#define INCLUDED_DTV_DVBT_INNER_CODER_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+#include <gnuradio/dtv/dvb_config.h>
+#include <gnuradio/dtv/dvbt_config.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Inner coder with Puncturing.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.3.3 \n
+ * Mother convolutional code with rate 1/2. \n
+ * k=1, n=2, K=6. \n
+ * Generator polynomial G1=171(OCT), G2=133(OCT). \n
+ * Punctured to obtain rates of 2/3, 3/4, 5/6, 7/8. \n
+ * Data Input format: Packed bytes (each bit is data). \n
+ * MSB - first, LSB last. \n
+ * Data Output format: \n
+ * 000000X0X1 - QPSK. \n
+ * 0000X0X1X2X3 - 16QAM. \n
+ * 00X0X1X2X3X4X5 - 64QAM.
+ */
+ class DTV_API dvbt_inner_coder : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_inner_coder> sptr;
+
+ /*!
+ * \brief Create an Inner coder with Puncturing.
+ *
+ * \param ninput length of input. \n
+ * \param noutput lenght of output. \n
+ * \param constellation type of constellation. \n
+ * \param hierarchy type of hierarchy used. \n
+ * \param coderate coderate used.
+ */
+ static sptr make(int ninput, int noutput, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_INNER_CODER_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_map.h b/gr-dtv/include/gnuradio/dtv/dvbt_map.h
new file mode 100644
index 0000000000..d9b7976b31
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_map.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DVBT_DVBT_MAP_H
+#define INCLUDED_DVBT_DVBT_MAP_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
+#include <gnuradio/dtv/dvbt_config.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief DVB-T mapper.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.3.5. \n
+ * Data input format: \n
+ * 000000Y0Y1 - QPSK. \n
+ * 0000Y0Y1Y2Y3 - 16QAM. \n
+ * 00Y0Y1Y2Y3Y4Y5 - 64QAM. \n
+ * Data output format: \n
+ * complex(real(float), imag(float)).
+ */
+ class DTV_API dvbt_map : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_map> sptr;
+
+ /*!
+ * \brief Create a DVB-T mapper.
+ *
+ * \param nsize length of input stream. \n
+ * \param constellation constellation used. \n
+ * \param hierarchy hierarchy used. \n
+ * \param transmission transmission mode used. \n
+ * \param gain gain of complex output stream.
+ */
+ static sptr make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_MAP_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_enc.h b/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_enc.h
new file mode 100644
index 0000000000..08c7c571fd
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_reed_solomon_enc.h
@@ -0,0 +1,61 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_REED_SOLOMON_ENC_H
+#define INCLUDED_DTV_DVBT_REED_SOLOMON_ENC_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Reed Solomon encoder
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.3.2 \n
+ * RS(N=204,K=239,T=8).
+ */
+ class DTV_API dvbt_reed_solomon_enc : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_reed_solomon_enc> sptr;
+
+ /*!
+ * \brief Create a Reed Solomon encoder.
+ *
+ * \param p characteristic of GF(p^m).
+ * \param m we use GF(p^m).
+ * \param gfpoly Generator Polynomial.
+ * \param n length of codeword of RS coder.
+ * \param k length of information sequence of RS encoder.
+ * \param t number of corrected errors.
+ * \param s shortened length.
+ * \param blocks number of blocks to process at once.
+ */
+ static sptr make(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_ENC_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_reference_signals.h b/gr-dtv/include/gnuradio/dtv/dvbt_reference_signals.h
new file mode 100644
index 0000000000..d41b949528
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_reference_signals.h
@@ -0,0 +1,71 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_H
+#define INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/dtv/dvb_config.h>
+#include <gnuradio/dtv/dvbt_config.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Reference signals generator.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.5 \n
+ * Data input format: \n
+ * complex(real(float), imag(float)). \n
+ * Data output format: \n
+ * complex(real(float), imag(float)).
+ */
+ class DTV_API dvbt_reference_signals : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_reference_signals> sptr;
+
+ /*!
+ * \brief Create Reference signals generator.
+ *
+ * \param itemsize size of an in/out item. \n
+ * \param ninput input stream length. \n
+ * \param noutput output stream length. \n
+ * \param constellation constellation used. \n
+ * \param hierarchy hierarchy used. \n
+ * \param code_rate_HP high priority stream code rate. \n
+ * \param code_rate_LP low priority stream code rate. \n
+ * \param guard_interval guard interval used. \n
+ * \param transmission_mode transmission mode used. \n
+ * \param include_cell_id include or not Cell ID. \n
+ * \param cell_id value of the Cell ID.
+ */
+ static sptr make(int itemsize, int ninput, int noutput, dvb_constellation_t constellation, \
+ dvbt_hierarchy_t hierarchy, dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, \
+ dvb_guardinterval_t guard_interval, dvbt_transmission_mode_t transmission_mode, int include_cell_id, int cell_id);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbt_symbol_inner_interleaver.h b/gr-dtv/include/gnuradio/dtv/dvbt_symbol_inner_interleaver.h
new file mode 100644
index 0000000000..ae02c9192f
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/dvbt_symbol_inner_interleaver.h
@@ -0,0 +1,66 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_SYMBOL_INNER_INTERLEAVER_H
+#define INCLUDED_DTV_DVBT_SYMBOL_INNER_INTERLEAVER_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+#include <gnuradio/dtv/dvbt_config.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Symbol interleaver.
+ * \ingroup dtv
+ *
+ * ETSI EN 300 744 Clause 4.3.4.2 \n
+ * One block is 12 groups x 126 datawords = 1512 datawords.
+ *
+ * Data Input format: \n
+ * 000000I0I1 - QPSK. \n
+ * 0000I0I1I2I3 - 16QAM. \n
+ * 00I0I1I2I3I4I5 - 64QAM. \n
+ * Data Output format: \n
+ * 000000Y0Y1 - QPSK. \n
+ * 0000Y0Y1Y2Y3 - 16QAM. \n
+ * 00Y0Y1Y2Y3Y4Y5 - 64QAM.
+ */
+ class DTV_API dvbt_symbol_inner_interleaver : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<dvbt_symbol_inner_interleaver> sptr;
+
+ /*!
+ * \brief Create a Symbol interleaver.
+ *
+ * \param ninput length of input stream. \n
+ * \param transmission transmission mode used \n
+ * \param direction interleave or deinterleave. \n
+ */
+ static sptr make(int ninput, dvbt_transmission_mode_t transmission, int direction);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_SYMBOL_INNER_INTERLEAVER_H */
+
diff --git a/gr-dtv/lib/CMakeLists.txt b/gr-dtv/lib/CMakeLists.txt
index 65f50e471d..f2128e9a83 100644
--- a/gr-dtv/lib/CMakeLists.txt
+++ b/gr-dtv/lib/CMakeLists.txt
@@ -94,6 +94,16 @@ list(APPEND dtv_sources
dvbs2/dvbs2_interleaver_bb_impl.cc
dvbs2/dvbs2_modulator_bc_impl.cc
dvbs2/dvbs2_physical_cc_impl.cc
+ dvbt/dvbt_energy_dispersal_impl.cc
+ dvbt/dvbt_reed_solomon.cc
+ dvbt/dvbt_reed_solomon_enc_impl.cc
+ dvbt/dvbt_convolutional_interleaver_impl.cc
+ dvbt/dvbt_configure.cc
+ dvbt/dvbt_inner_coder_impl.cc
+ dvbt/dvbt_bit_inner_interleaver_impl.cc
+ dvbt/dvbt_symbol_inner_interleaver_impl.cc
+ dvbt/dvbt_map_impl.cc
+ dvbt/dvbt_reference_signals_impl.cc
)
if(ENABLE_GR_CTRLPORT)
diff --git a/gr-dtv/lib/dvb/dvb_bbheader_bb_impl.cc b/gr-dtv/lib/dvb/dvb_bbheader_bb_impl.cc
index e0c80ea304..551191c0e5 100644
--- a/gr-dtv/lib/dvb/dvb_bbheader_bb_impl.cc
+++ b/gr-dtv/lib/dvb/dvb_bbheader_bb_impl.cc
@@ -406,29 +406,24 @@ namespace gr {
m_frame[0] = 0;
m_frame[1] = 1;
m_frame_offset_bits = 2;
- temp = 0;
for (int n = 30; n >= 0; n--) {
- m_frame[m_frame_offset_bits++] = temp & (1 << n) ? 1 : 0;
+ m_frame[m_frame_offset_bits++] = 0;
}
- temp = 0;
for (int n = 21; n >= 0; n--) {
- m_frame[m_frame_offset_bits++] = temp & (1 << n) ? 1 : 0;
+ m_frame[m_frame_offset_bits++] = 0;
}
- temp = 0;
for (int n = 1; n >= 0; n--) {
- m_frame[m_frame_offset_bits++] = temp & (1 << n) ? 1 : 0;
+ m_frame[m_frame_offset_bits++] = 0;
}
- temp = 0;
for (int n = 9; n >= 0; n--) {
- m_frame[m_frame_offset_bits++] = temp & (1 << n) ? 1 : 0;
+ m_frame[m_frame_offset_bits++] = 0;
}
temp = ts_rate;
for (int n = 26; n >= 0; n--) {
m_frame[m_frame_offset_bits++] = temp & (1 << n) ? 1 : 0;
}
- temp = 0;
for (int n = 9; n >= 0; n--) {
- m_frame[m_frame_offset_bits++] = temp & (1 << n) ? 1 : 0;
+ m_frame[m_frame_offset_bits++] = 0;
}
}
diff --git a/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h b/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h
index 3510ddf083..92c9eb370e 100644
--- a/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h
+++ b/gr-dtv/lib/dvb/dvb_ldpc_bb_impl.h
@@ -42,7 +42,6 @@ namespace gr {
unsigned int nbch;
unsigned int code_rate;
unsigned int q_val;
- unsigned int table_length;
unsigned int dvb_standard;
void ldpc_lookup_generate(void);
ldpc_encode_table ldpc_encode;
diff --git a/gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.cc
new file mode 100644
index 0000000000..0ab3003d50
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.cc
@@ -0,0 +1,191 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_bit_inner_interleaver_impl.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace dtv {
+
+ const int dvbt_bit_inner_interleaver_impl::d_bsize = 126;
+
+ int
+ dvbt_bit_inner_interleaver_impl::H(int e, int w)
+ {
+ int rez = 0;
+
+ switch (e) {
+ case 0:
+ rez = w;
+ break;
+ case 1:
+ rez = (w + 63) % d_bsize;
+ break;
+ case 2:
+ rez = (w + 105) % d_bsize;
+ break;
+ case 3:
+ rez = (w + 42) % d_bsize;
+ break;
+ case 4:
+ rez = (w + 21) % d_bsize;
+ break;
+ case 5:
+ rez = (w + 84) % d_bsize;
+ break;
+ default:
+ break;
+ }
+
+ return rez;
+ }
+
+ dvbt_bit_inner_interleaver::sptr
+ dvbt_bit_inner_interleaver::make(int nsize, \
+ dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_bit_inner_interleaver_impl(nsize, constellation, hierarchy, transmission));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_bit_inner_interleaver_impl::dvbt_bit_inner_interleaver_impl(int nsize, dvb_constellation_t constellation, \
+ dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission)
+ : block("dvbt_bit_inner_interleaver",
+ io_signature::make(1, 2, sizeof(unsigned char) * nsize),
+ io_signature::make(1, 1, sizeof (unsigned char) * nsize)),
+ config(constellation, hierarchy, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission),
+ d_nsize(nsize),
+ d_hierarchy(hierarchy)
+ {
+ d_v = config.d_m;
+ d_hierarchy = config.d_hierarchy;
+
+ d_perm = (unsigned char *)new unsigned char[d_v * d_bsize];
+ if (d_perm == NULL) {
+ std::cout << "Cannot allocate memory for d_perm" << std::endl;
+ exit(1);
+ }
+
+ //Init permutation table (used for b[e][do])
+ for (int i = 0; i < d_bsize * d_v; i++) {
+ if (d_hierarchy == NH) {
+ d_perm[i] = ((i % d_v) / (d_v / 2)) + 2 * (i % (d_v / 2));
+ }
+ else {
+ d_perm[i] = (i % (d_v - 2)) / ((d_v - 2) / 2) + 2 * (i % ((d_v - 2) / 2)) + 2;
+ }
+ }
+
+ if (d_nsize % d_bsize) {
+ std::cout << "Error: Input size must be multiple of block size: " \
+ << "nsize: " << d_nsize << "bsize: " << d_bsize << std::endl;
+ }
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_bit_inner_interleaver_impl::~dvbt_bit_inner_interleaver_impl()
+ {
+ delete [] d_perm;
+ }
+
+ void
+ dvbt_bit_inner_interleaver_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ ninput_items_required[1] = noutput_items;
+ }
+
+ int
+ dvbt_bit_inner_interleaver_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *inh = (const unsigned char *) input_items[0];
+ const unsigned char *inl = (const unsigned char *) input_items[1];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ int bmax = noutput_items * d_nsize / d_bsize;
+
+ // First index of d_b is Bit interleaver number
+ // Second index of d_b is the position inside the Bit interleaver
+ unsigned char d_b[d_v][d_bsize];
+
+ for (int bcount = 0; bcount < bmax; bcount++) {
+ for (int i = 0; i < d_bsize; i++) {
+ if (d_hierarchy == NH) {
+ int c = inh[bcount * d_bsize + i];
+
+ // Create the demultiplexer
+ for (int k = 0; k < d_v; k++) {
+ d_b[d_perm[(d_v * i) + k]][i] = (c >> (d_v - k - 1)) & 1;
+ }
+ }
+ else {
+ int ch = inh[(bcount * d_bsize) + i];
+ int cl = inl[(bcount * d_bsize) + i];
+
+ // High priority input - first 2 streams
+ for (int k = 0; k < 2; k++) {
+ d_b[(d_v * i + k) % 2][(d_v * i + k) / 2] = (ch >> (1 - k)) & 1;
+ }
+
+ // Low priority input - (v - 2) streams
+ for (int k = 2; k < (d_v - 2); k++) {
+ d_b[d_perm[d_v * i + k]][(d_v * i + k) / (d_v - 2)] = (cl >> (d_v - k - 1)) & 1;
+ }
+ }
+ }
+
+ // Take one bit from each interleaver
+ // and format the output
+
+ for (int w = 0; w < d_bsize; w++) {
+ int val = 0;
+
+ for (int e = 0; e < d_v; e++) {
+ val = (val << 1) | d_b[e][H(e, w)];
+ }
+
+ out[(bcount * d_bsize) + w] = val;
+ }
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (noutput_items);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.h
new file mode 100644
index 0000000000..c5fcbe2d82
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_bit_inner_interleaver_impl.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_BIT_INNER_INTERLEAVER_IMPL_H
+#define INCLUDED_DTV_DVBT_BIT_INNER_INTERLEAVER_IMPL_H
+
+#include <gnuradio/dtv/dvbt_bit_inner_interleaver.h>
+#include "dvbt_configure.h"
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_bit_inner_interleaver_impl : public dvbt_bit_inner_interleaver
+ {
+ private:
+ const dvbt_configure config;
+
+ int d_nsize;
+ dvbt_hierarchy_t d_hierarchy;
+
+ // constellation
+ int d_v;
+ // Bit interleaver block size
+ static const int d_bsize;
+
+ // Table to keep interleaved indices
+ unsigned char * d_perm;
+
+ // Permutation function
+ int H(int e, int w);
+
+ public:
+ dvbt_bit_inner_interleaver_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission);
+ ~dvbt_bit_inner_interleaver_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_BIT_INNER_INTERLEAVER_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_configure.cc b/gr-dtv/lib/dvbt/dvbt_configure.cc
new file mode 100644
index 0000000000..a6d1af7874
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_configure.cc
@@ -0,0 +1,277 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_configure.h"
+#include <iostream>
+#include <stdio.h>
+
+namespace gr {
+ namespace dtv {
+
+ void
+ dvbt_configure::set_frame_number(int fn)
+ {
+ d_frame_index = fn;
+ }
+ int
+ dvbt_configure::get_frame_mumber()
+ {
+ return (d_frame_index);
+ }
+ void
+ dvbt_configure::set_constellation(dvb_constellation_t constellation)
+ {
+ d_constellation = constellation;
+ }
+ dvb_constellation_t
+ dvbt_configure::get_constellation()
+ {
+ return (d_constellation);
+ }
+ void
+ dvbt_configure::set_hierarchical(dvbt_hierarchy_t hierarchy)
+ {
+ d_hierarchy = hierarchy;
+ }
+ dvbt_hierarchy_t
+ dvbt_configure::get_hierarchical()
+ {
+ return d_hierarchy;
+ }
+ void
+ dvbt_configure::set_code_rate_HP(dvb_code_rate_t code_rate)
+ {
+ d_code_rate_HP = code_rate;
+ }
+ void
+ dvbt_configure::set_code_rate_LP(dvb_code_rate_t code_rate)
+ {
+ d_code_rate_LP = code_rate;
+ }
+ dvb_code_rate_t
+ dvbt_configure::get_code_rate_HP()
+ {
+ return d_code_rate_HP;
+ }
+ dvb_code_rate_t
+ dvbt_configure::get_code_rate_LP()
+ {
+ return d_code_rate_LP;
+ }
+ void
+ dvbt_configure::set_transmission_mode(dvbt_transmission_mode_t transmission_mode)
+ {
+ d_transmission_mode = transmission_mode;
+ }
+ dvbt_transmission_mode_t
+ dvbt_configure::get_transmission_mode()
+ {
+ return d_transmission_mode;
+ }
+
+ dvbt_configure::dvbt_configure(dvb_constellation_t constellation, \
+ dvbt_hierarchy_t hierarchy, dvb_code_rate_t code_rate_HP, \
+ dvb_code_rate_t code_rate_LP, dvb_guardinterval_t guard_interval, \
+ dvbt_transmission_mode_t transmission_mode, int include_cell_id, int cell_id) :
+ d_constellation(constellation), d_hierarchy(hierarchy), d_code_rate_HP(code_rate_HP),
+ d_code_rate_LP(code_rate_LP), d_guard_interval(guard_interval), d_transmission_mode(transmission_mode),
+ d_include_cell_id(include_cell_id), d_cell_id(cell_id)
+ {
+ d_symbols_per_frame = 68;
+ d_frames_per_superframe = 4;
+ d_symbol_index = 0;
+ d_frame_index = 0;
+ d_superframe_index = 0;
+
+ switch (d_transmission_mode) {
+ case T2k:
+ d_Kmin = 0; d_Kmax = 1704;
+ d_fft_length = 2048;
+ d_payload_length = 1512;
+ break;
+ case T8k:
+ d_Kmin = 0; d_Kmax = 6816;
+ d_fft_length = 8192;
+ d_payload_length = 6048;
+ break;
+ default:
+ d_Kmin = 0; d_Kmax = 1704;
+ d_fft_length = 2048;
+ d_payload_length = 1512;
+ break;
+ }
+ d_zeros_on_left = int(ceil((d_fft_length - (d_Kmax - d_Kmin + 1)) / 2.0));
+ d_zeros_on_right = d_fft_length - d_zeros_on_left - (d_Kmax - d_Kmin + 1);
+
+ switch (d_constellation) {
+ case MOD_QPSK:
+ d_constellation_size = 4;
+ d_step = 2;
+ d_m = 2;
+ break;
+ case MOD_16QAM:
+ d_constellation_size = 16;
+ d_step = 2;
+ d_m = 4;
+ break;
+ case MOD_64QAM:
+ d_constellation_size = 64;
+ d_step = 2;
+ d_m = 6;
+ break;
+ default:
+ d_constellation_size = 16;
+ d_step = 2;
+ d_m = 4;
+ break;
+ }
+
+ switch (d_code_rate_HP) {
+ case C1_2:
+ d_cr_k = 1; d_cr_n = 2; d_cr_p = 1;
+ break;
+ case C2_3:
+ d_cr_k = 2; d_cr_n = 3; d_cr_p = 2;
+ break;
+ case C3_4:
+ d_cr_k = 3; d_cr_n = 4; d_cr_p = 3;
+ break;
+ case C5_6:
+ d_cr_k = 5; d_cr_k = 6; d_cr_p = 5;
+ break;
+ case C7_8:
+ d_cr_k = 7; d_cr_n = 8; d_cr_p = 7;
+ break;
+ default:
+ d_cr_k = 1; d_cr_n = 2; d_cr_p = 1;
+ break;
+ }
+
+ switch (d_code_rate_LP) {
+ case C1_2:
+ d_cr_k = 1; d_cr_n = 2;
+ break;
+ case C2_3:
+ d_cr_k = 2; d_cr_n = 3;
+ break;
+ case C3_4:
+ d_cr_k = 3; d_cr_n = 4;
+ break;
+ case C5_6:
+ d_cr_k = 5; d_cr_n = 6;
+ break;
+ case C7_8:
+ d_cr_k = 7; d_cr_n = 8;
+ break;
+ default:
+ d_cr_k = 1; d_cr_n = 2;
+ break;
+ }
+
+ switch (guard_interval) {
+ case GI_1_32:
+ d_cp_length = d_fft_length / 32;
+ break;
+ case GI_1_16:
+ d_cp_length = d_fft_length / 16;
+ break;
+ case GI_1_8:
+ d_cp_length = d_fft_length / 8;
+ break;
+ case GI_1_4:
+ d_cp_length = d_fft_length / 4;
+ break;
+ default:
+ d_cp_length = d_fft_length / 32;
+ break;
+ }
+
+ switch (d_hierarchy) {
+ case NH:
+ d_alpha = 1;
+ break;
+ case ALPHA1:
+ d_alpha = 1;
+ break;
+ case ALPHA2:
+ d_alpha = 2;
+ break;
+ case ALPHA4:
+ d_alpha = 4;
+ break;
+ default:
+ d_alpha = 1;
+ break;
+ }
+
+ // ETSI EN 400 744 Clause 4.4
+ // Normalization factor
+ switch (d_m) {
+ case 2:
+ d_norm = 1.0 / sqrt(2);
+ break;
+ case 4:
+ if (d_alpha == 1) {
+ d_norm = 1.0 / sqrt(10);
+ }
+ if (d_alpha == 2) {
+ d_norm = 1.0 / sqrt(20);
+ }
+ if (d_alpha == 4) {
+ d_norm = 1.0 / sqrt(52);
+ }
+ break;
+ case 6:
+ if (d_alpha == 1) {
+ d_norm = 1.0 / sqrt(42);
+ }
+ if (d_alpha == 2) {
+ d_norm = 1.0 / sqrt(60);
+ }
+ if (d_alpha == 4) {
+ d_norm = 1.0 / sqrt(108);
+ }
+ break;
+ default:
+ if (d_alpha == 1) {
+ d_norm = 1.0 / sqrt(10);
+ }
+ if (d_alpha == 2) {
+ d_norm = 1.0 / sqrt(20);
+ }
+ if (d_alpha == 4) {
+ d_norm = 1.0 / sqrt(52);
+ }
+ break;
+ }
+ }
+
+ dvbt_configure::~dvbt_configure()
+ {
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_configure.h b/gr-dtv/lib/dvbt/dvbt_configure.h
new file mode 100644
index 0000000000..5e87410c90
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_configure.h
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_CONFIGURE_H
+#define INCLUDED_DTV_DVBT_CONFIGURE_H
+
+#include <gnuradio/dtv/dvb_config.h>
+#include <gnuradio/dtv/dvbt_config.h>
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_configure
+ {
+ public:
+ int d_symbols_per_frame;
+ int d_frames_per_superframe;
+
+ int d_symbol_index;
+ int d_frame_index;
+ int d_superframe_index;
+
+ //Constelaltion parameters
+ dvb_constellation_t d_constellation;
+ int d_constellation_size;
+ int d_step;
+ int d_m;
+ float d_norm;
+
+ //Hierarchy information
+ dvbt_hierarchy_t d_hierarchy;
+ int d_alpha;
+
+ //Inner Coding parameters
+ dvb_code_rate_t d_code_rate_HP;
+ dvb_code_rate_t d_code_rate_LP;
+
+ // Guard interval length
+ dvb_guardinterval_t d_guard_interval;
+
+ //Transmission type parameters
+ dvbt_transmission_mode_t d_transmission_mode;
+
+ //Include cell id + cell id parameters
+ int d_include_cell_id;
+ int d_cell_id;
+
+ // Puncturer parameters
+ int d_cr_k;
+ int d_cr_n;
+ int d_cr_p;
+
+ //Other DVB-T parameters
+ int d_Kmin;
+ int d_Kmax;
+ int d_fft_length;
+ int d_payload_length;
+ int d_zeros_on_left;
+ int d_zeros_on_right;
+ int d_cp_length;
+
+ void set_frame_number(int fn);
+ int get_frame_mumber();
+ void set_constellation(dvb_constellation_t constellation);
+ dvb_constellation_t get_constellation();
+ void set_hierarchical(dvbt_hierarchy_t hierarchy);
+ dvbt_hierarchy_t get_hierarchical();
+ void set_code_rate_HP(dvb_code_rate_t coderate);
+ dvb_code_rate_t get_code_rate_HP();
+ void set_code_rate_LP(dvb_code_rate_t coderate);
+ dvb_code_rate_t get_code_rate_LP();
+ void set_transmission_mode(dvbt_transmission_mode_t transmission_mode);
+ dvbt_transmission_mode_t get_transmission_mode();
+
+ dvbt_configure(dvb_constellation_t constellation = gr::dtv::MOD_16QAM, \
+ dvbt_hierarchy_t hierarchy = gr::dtv::NH, dvb_code_rate_t code_rate_HP = gr::dtv::C1_2, \
+ dvb_code_rate_t code_rate_LP = gr::dtv::C1_2, dvb_guardinterval_t guard_interval = gr::dtv::GI_1_32, \
+ dvbt_transmission_mode_t transmission_mode = gr::dtv::T2k, int include_cell_id = 0, int cell_id = 0);
+ ~dvbt_configure();
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_CONFIGURE_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.cc
new file mode 100644
index 0000000000..e29ec8cfe2
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.cc
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_convolutional_interleaver_impl.h"
+#include <deque>
+
+namespace gr {
+ namespace dtv {
+
+ dvbt_convolutional_interleaver::sptr
+ dvbt_convolutional_interleaver::make(int nsize, int I, int M)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_convolutional_interleaver_impl(nsize, I, M));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_convolutional_interleaver_impl::dvbt_convolutional_interleaver_impl(int blocks, int I, int M)
+ : sync_interpolator("dvbt_convolutional_interleaver",
+ io_signature::make(1, 1, sizeof (unsigned char) * I * blocks),
+ io_signature::make(1, 1, sizeof (unsigned char)), I * blocks),
+ d_blocks(blocks), d_I(I), d_M(M)
+ {
+ //Positions are shift registers (FIFOs)
+ //of length i*M
+ for (int i = 0; i < d_I; i++) {
+ d_shift.push_back(new std::deque<unsigned char>(d_M * i, 0));
+ }
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_convolutional_interleaver_impl::~dvbt_convolutional_interleaver_impl()
+ {
+ for (unsigned int i = 0; i < d_shift.size(); i++) {
+ delete d_shift.back();
+ d_shift.pop_back();
+ }
+ }
+
+ int
+ dvbt_convolutional_interleaver_impl::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ for (int i = 0; i < (noutput_items / d_I); i++) {
+ //Process one block of I symbols
+ for (unsigned int j = 0; j < d_shift.size(); j++) {
+ d_shift[j]->push_front(in[(d_I * i) + j]);
+ out[(d_I * i) + j] = d_shift[j]->back();
+ d_shift[j]->pop_back();
+ }
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.h
new file mode 100644
index 0000000000..2de1fab282
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_convolutional_interleaver_impl.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_CONVOLUTIONAL_INTERLEAVER_IMPL_H
+#define INCLUDED_DTV_DVBT_CONVOLUTIONAL_INTERLEAVER_IMPL_H
+
+#include <gnuradio/dtv/dvbt_convolutional_interleaver.h>
+#include <vector>
+#include <deque>
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_convolutional_interleaver_impl : public dvbt_convolutional_interleaver
+ {
+ private:
+ int d_blocks;
+ int d_I;
+ int d_M;
+ std::vector< std::deque<unsigned char> * > d_shift;
+
+ public:
+ dvbt_convolutional_interleaver_impl(int nsize, int I, int M);
+ ~dvbt_convolutional_interleaver_impl();
+
+ int work(int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_CONVOLUTIONAL_INTERLEAVER_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.cc b/gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.cc
new file mode 100644
index 0000000000..03dd0ffec5
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.cc
@@ -0,0 +1,151 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_energy_dispersal_impl.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace dtv {
+
+ const int dvbt_energy_dispersal_impl::d_npacks = 8;
+ const int dvbt_energy_dispersal_impl::d_psize = 188;
+ const int dvbt_energy_dispersal_impl::d_SYNC = 0x47;
+ const int dvbt_energy_dispersal_impl::d_NSYNC = 0xB8;
+
+ void
+ dvbt_energy_dispersal_impl::init_prbs()
+ {
+ d_reg = 0xa9;
+ }
+
+ int
+ dvbt_energy_dispersal_impl::clock_prbs(int clocks)
+ {
+ int res = 0;
+ int feedback = 0;
+
+ for (int i = 0; i < clocks; i++) {
+ feedback = ((d_reg >> (14 - 1)) ^ (d_reg >> (15 - 1))) & 0x1;
+ d_reg = ((d_reg << 1) | feedback) & 0x7fff;
+ res = (res << 1) | feedback;
+ }
+ return res;
+ }
+
+ dvbt_energy_dispersal::sptr
+ dvbt_energy_dispersal::make(int nblocks)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_energy_dispersal_impl(nblocks));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_energy_dispersal_impl::dvbt_energy_dispersal_impl(int nblocks)
+ : gr::block("dvbt_energy_dispersal",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(unsigned char) * nblocks * d_npacks * d_psize)),
+ d_nblocks(nblocks),
+ d_reg(0xa9)
+ {
+ set_relative_rate(1.0/(double) (d_nblocks * d_npacks * d_psize));
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_energy_dispersal_impl::~dvbt_energy_dispersal_impl()
+ {
+ }
+
+ void
+ dvbt_energy_dispersal_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ // Add one block size for SYNC search
+ ninput_items_required[0] = d_npacks * (d_psize + 1) * d_nblocks * noutput_items;
+ }
+
+ int
+ dvbt_energy_dispersal_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ int index = 0;
+ int count = 0;
+ int ret = 0;
+ int is_sync = 0;
+
+ // Search for SYNC byte
+ while (is_sync == 0 && index < d_psize) {
+ if (in[index] == d_SYNC) {
+ is_sync = 1;
+ }
+ else {
+ index++;
+ }
+ }
+
+ // If we found a SYNC byte
+ if (is_sync) {
+ for (int i = 0; i < (d_nblocks * noutput_items); i++) {
+ init_prbs();
+
+ int sync = d_NSYNC;
+
+ for (int j = 0; j < d_npacks; j++) {
+ if (in[index + count] != d_SYNC) {
+ printf("error: Malformed MPEG-TS!\n");
+ }
+
+ out[count++] = sync;
+
+ for (int k = 1; k < d_psize; k++) {
+ out[count] = in[index + count] ^ clock_prbs(d_npacks);
+ count++;
+ }
+
+ sync = d_SYNC;
+ clock_prbs(d_npacks);
+ }
+ }
+ consume_each(index + d_npacks * d_psize * d_nblocks * noutput_items);
+ ret = noutput_items;
+ }
+ else {
+ consume_each(index);
+ ret = 0;
+ }
+
+ // Tell runtime system how many output items we produced.
+ return ret;
+ }
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.h b/gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.h
new file mode 100644
index 0000000000..e1cfe4e925
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_energy_dispersal_impl.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_ENERGY_DISPERSAL_IMPL_H
+#define INCLUDED_DTV_DVBT_ENERGY_DISPERSAL_IMPL_H
+
+#include <gnuradio/dtv/dvbt_energy_dispersal.h>
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_energy_dispersal_impl : public dvbt_energy_dispersal
+ {
+ private:
+ // Packet size
+ static const int d_psize;
+ // Number of packets after which PRBS is reset
+ static const int d_npacks;
+ // Number of blocks
+ int d_nblocks;
+ // SYNC value
+ static const int d_SYNC;
+ // Negative SYNC value
+ static const int d_NSYNC;
+
+ // Register for PRBS
+ int d_reg;
+
+ void init_prbs();
+ int clock_prbs(int clocks);
+
+ public:
+ dvbt_energy_dispersal_impl(int nsize);
+ ~dvbt_energy_dispersal_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_ENERGY_DISPERSAL_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_inner_coder_impl.cc b/gr-dtv/lib/dvbt/dvbt_inner_coder_impl.cc
new file mode 100644
index 0000000000..4f24f0258f
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_inner_coder_impl.cc
@@ -0,0 +1,257 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_inner_coder_impl.h"
+#include <stdio.h>
+#include <assert.h>
+
+namespace gr {
+ namespace dtv {
+
+ void
+ dvbt_inner_coder_impl::generate_codeword(unsigned char in, int &x, int &y)
+ {
+ //insert input bit
+ d_reg |= ((in & 0x1) << 7);
+
+ d_reg = d_reg >> 1;
+
+ // TODO - do this with polynoms and bitcnt
+ //generate output G1=171(OCT)
+ x = ((d_reg >> 6) ^ (d_reg >> 5) ^ (d_reg >> 4) ^ \
+ (d_reg >> 3) ^ d_reg) & 0x1;
+ //generate output G2=133(OCT)
+ y = ((d_reg >> 6) ^ (d_reg >> 4) ^ (d_reg >> 3) ^ \
+ (d_reg >> 1) ^ d_reg) & 0x1;
+ }
+
+ //TODO - do this based on puncturing matrix
+ /*
+ * Input e.g rate 2/3:
+ * 000000x0x1
+ * Output e.g. rate 2/3
+ * 00000c0c1c2
+ */
+
+ void
+ dvbt_inner_coder_impl::generate_punctured_code(dvb_code_rate_t coderate, unsigned char * in, unsigned char * out)
+ {
+ int x, y;
+
+ switch(coderate) {
+ //X1Y1
+ case C1_2:
+ generate_codeword(in[0], x, y);
+ out[0] = x; out[1] = y;
+ break;
+ //X1Y1Y2
+ case C2_3:
+ generate_codeword(in[0], x, y);
+ out[0] = x; out[1] = y;
+ generate_codeword(in[1], x, y);
+ out[2] = y;
+ break;
+ //X1Y1Y2X3
+ case C3_4:
+ generate_codeword(in[0], x, y);
+ out[0] = x; out[1] = y;
+ generate_codeword(in[1], x, y);
+ out[2] = y;
+ generate_codeword(in[2], x, y);
+ out[3] = x;
+ break;
+ //X1Y1Y2X3Y4X5
+ case C5_6:
+ generate_codeword(in[0], x, y);
+ out[0] = x; out[1] = y;
+ generate_codeword(in[1], x, y);
+ out[2] = y;
+ generate_codeword(in[2], x, y);
+ out[3] = x;
+ generate_codeword(in[3], x, y);
+ out[4] = y;
+ generate_codeword(in[4], x, y);
+ out[5] = x;
+ break;
+ //X1Y1Y2X3Y4X5Y6X7
+ case C7_8:
+ generate_codeword(in[0], x, y);
+ out[0] = x; out[1] = y;
+ generate_codeword(in[1], x, y);
+ out[2] = y;
+ generate_codeword(in[2], x, y);
+ out[3] = y;
+ generate_codeword(in[3], x, y);
+ out[4] = y;
+ generate_codeword(in[4], x, y);
+ out[5] = x;
+ generate_codeword(in[5], x, y);
+ out[6] = y;
+ generate_codeword(in[6], x, y);
+ out[7] = x;
+ break;
+ default:
+ generate_codeword(in[0], x, y);
+ out[0] = x; out[1] = y;
+ break;
+ }
+ }
+
+ dvbt_inner_coder::sptr
+ dvbt_inner_coder::make(int ninput, int noutput, dvb_constellation_t constellation, \
+ dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_inner_coder_impl(ninput, noutput, constellation, hierarchy, coderate));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_inner_coder_impl::dvbt_inner_coder_impl(int ninput, int noutput, dvb_constellation_t constellation, \
+ dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate)
+ : block("dvbt_inner_coder",
+ io_signature::make(1, 1, sizeof (unsigned char)),
+ io_signature::make(1, 1, sizeof (unsigned char) * noutput)),
+ config(constellation, hierarchy, coderate, coderate),
+ d_ninput(ninput), d_noutput(noutput),
+ d_reg(0),
+ d_bitcount(0)
+ {
+ //Determine k - input of encoder
+ d_k = config.d_cr_k;
+ //Determine n - output of encoder
+ d_n = config.d_cr_n;
+ //Determine m - constellation symbol size
+ d_m = config.d_m;
+
+ // In order to accomodate all constalations (m=2,4,6)
+ // and rates (1/2, 2/3, 3/4, 5/6, 7/8)
+ // We need the following things to happen:
+ // - output item size multiple of 1512bytes
+ // - noutput_items multiple of 4
+ // - in block size 4*(k*m/8)
+ // - out block size 4*n
+ //
+ // Rate calculation follows:
+ // We process km input bits(km/8 Bytes)
+ // We output nm bits
+ // We output one byte for a symbol of m bits
+ // The out/in rate in bytes is: 8n/km (Bytes)
+
+ assert(d_ninput % 1);
+ assert(d_noutput % 1512);
+
+ // Set output items multiple of 4
+ set_output_multiple(4);
+
+ // Set relative rate out/in
+ assert((d_noutput * d_k * d_m) % (d_ninput * 8 * d_n));
+ set_relative_rate((float)(d_ninput * 8 * d_n) / (float)d_noutput * d_k * d_m);
+
+ // calculate in and out block sizes
+ d_in_bs = (d_k * d_m) / 2;
+ d_out_bs = 4 * d_n;
+
+ // allocate bit buffers
+ d_in_buff = new unsigned char[8 * d_in_bs];
+ if (d_in_buff == NULL) {
+ std::cout << "Cannot allocate memory for d_in_buff" << std::endl;
+ exit(1);
+ }
+
+ d_out_buff = new unsigned char[8 * d_in_bs * d_n / d_k];
+ if (d_out_buff == NULL) {
+ std::cout << "Cannot allocate memory for d_out_buff" << std::endl;
+ delete [] d_in_buff;
+ exit(1);
+ }
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_inner_coder_impl::~dvbt_inner_coder_impl()
+ {
+ delete [] d_out_buff;
+ delete [] d_in_buff;
+ }
+
+ void
+ dvbt_inner_coder_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ int input_required = noutput_items * d_noutput * d_k * d_m / (d_ninput * 8 * d_n);
+
+ unsigned ninputs = ninput_items_required.size();
+ for (unsigned int i = 0; i < ninputs; i++) {
+ ninput_items_required[i] = input_required;
+ }
+ }
+
+ int
+ dvbt_inner_coder_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ for (int k = 0; k < (noutput_items * d_noutput / d_out_bs); k++) {
+ // Unpack input to bits
+ for (int i = 0; i < d_in_bs; i++) {
+ for (int j = 0; j < 8; j++) {
+ d_in_buff[8*i + j] = (in[k*d_in_bs + i] >> (7 - j)) & 1;
+ }
+ }
+
+ // Encode the data
+ for (int in_bit = 0, out_bit = 0; in_bit < (8 * d_in_bs); in_bit += d_k, out_bit += d_n) {
+ generate_punctured_code(config.d_code_rate_HP, &d_in_buff[in_bit], &d_out_buff[out_bit]);
+ }
+
+ // Pack d_m bit in one output byte
+ for (int i = 0; i < d_out_bs; i++) {
+ unsigned char c = 0;
+
+ for (int j = 0; j < d_m; j++) {
+ c |= d_out_buff[d_m*i + j] << (d_m - 1 - j);
+ }
+
+ out[k*d_out_bs + i] = c;
+ }
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each(noutput_items * d_noutput * d_k * d_m / (d_ninput * 8 * d_n));
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_inner_coder_impl.h b/gr-dtv/lib/dvbt/dvbt_inner_coder_impl.h
new file mode 100644
index 0000000000..7a46a2222c
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_inner_coder_impl.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_INNER_CODER_IMPL_H
+#define INCLUDED_DTV_DVBT_INNER_CODER_IMPL_H
+
+#include <gnuradio/dtv/dvbt_inner_coder.h>
+#include "dvbt_configure.h"
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_inner_coder_impl : public dvbt_inner_coder
+ {
+ private:
+ const dvbt_configure config;
+
+ int d_ninput;
+ int d_noutput;
+
+ int d_reg;
+
+ //counts the bits in the bytes
+ //in input stream
+ int d_bitcount;
+
+ // Code rate k/n
+ int d_k;
+ int d_n;
+ // Constellation with m
+ int d_m;
+
+ // input block size in bytes
+ int d_in_bs;
+ // bit input buffer
+ unsigned char * d_in_buff;
+
+ // output block size in bytes
+ int d_out_bs;
+ // bit output buffer
+ unsigned char * d_out_buff;
+
+ void generate_codeword(unsigned char in, int &x, int &y);
+ void generate_punctured_code(dvb_code_rate_t coderate, unsigned char * in, unsigned char * out);
+
+ public:
+ dvbt_inner_coder_impl(int ninput, int noutput, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvb_code_rate_t coderate);
+ ~dvbt_inner_coder_impl();
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_INNER_CODER_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_map_impl.cc b/gr-dtv/lib/dvbt/dvbt_map_impl.cc
new file mode 100644
index 0000000000..05f6e7f69b
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_map_impl.cc
@@ -0,0 +1,163 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include <complex>
+#include "dvbt_map_impl.h"
+#include <stdio.h>
+#include <math.h>
+
+namespace gr {
+ namespace dtv {
+
+ dvbt_map::sptr
+ dvbt_map::make(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_map_impl(nsize, constellation, hierarchy, transmission, gain));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_map_impl::dvbt_map_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain)
+ : block("dvbt_map",
+ io_signature::make(1, 1, sizeof (unsigned char) * nsize),
+ io_signature::make(1, 1, sizeof (gr_complex) * nsize)),
+ config(constellation, hierarchy, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission),
+ d_nsize(nsize),
+ d_constellation_size(0),
+ d_step(0),
+ d_alpha(0),
+ d_gain(0.0)
+ {
+ //Get parameters from config object
+ d_constellation_size = config.d_constellation_size;
+ d_transmission_mode = config.d_transmission_mode;
+ d_step = config.d_step;
+ d_alpha = config.d_alpha;
+ d_gain = gain * config.d_norm;
+
+ d_constellation_points = new gr_complex[d_constellation_size];
+ if (d_constellation_points == NULL) {
+ std::cout << "Cannot allocate memory for d_constellation_points" << std::endl;
+ exit(1);
+ }
+
+ make_constellation_points(d_constellation_size, d_step, d_alpha);
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_map_impl::~dvbt_map_impl()
+ {
+ delete [] d_constellation_points;
+ }
+
+ unsigned int
+ dvbt_map_impl::bin_to_gray(unsigned int val)
+ {
+ return (val >> 1) ^ val;
+ }
+
+ void
+ dvbt_map_impl::make_constellation_points(int size, int step, int alpha)
+ {
+ // The symmetry of the constellation is used to calculate
+ // 16-QAM from QPSK and 64-QAM form 16-QAM
+
+ int bits_per_axis = log2(size) / 2;
+ int steps_per_axis = sqrt(size) / 2 - 1;
+
+ for (int i = 0; i < size; i++) {
+ // This is the quadrant made of the first two bits starting from MSB
+ int q = i >> (2 * (bits_per_axis - 1)) & 3;
+ // Sign for correctly calculate I and Q in each quadrant
+ int sign0 = (q >> 1) ? -1 : 1; int sign1 = (q & 1) ? -1 : 1;
+
+ int x = (i >> (bits_per_axis - 1)) & ((1 << (bits_per_axis - 1)) - 1);
+ int y = i & ((1 << (bits_per_axis - 1)) - 1);
+
+ int xval = alpha + (steps_per_axis - x) * step;
+ int yval = alpha + (steps_per_axis - y) * step;
+
+ int val = (bin_to_gray(x) << (bits_per_axis - 1)) + bin_to_gray(y);
+
+ // ETSI EN 300 744 Clause 4.3.5
+ // Actually the constellation is gray coded
+ // but the bits on each axis are not taken in consecutive order
+ // So we need to convert from b0b2b4b1b3b5->b0b1b2b3b4b5(QAM64)
+
+ x = 0; y = 0;
+
+ for (int j = 0; j < (bits_per_axis - 1); j++) {
+ x += ((val >> (1 + 2 * j)) & 1) << j;
+ y += ((val >> (2 * j)) & 1) << j;
+ }
+
+ val = (q << 2 * (bits_per_axis - 1)) + (x << (bits_per_axis - 1)) + y;
+
+ // Keep corresponding symbol bits->complex symbol in one vector
+ // Normalize the signal using gain
+ d_constellation_points[val] = d_gain * gr_complex(sign0 * xval, sign1 * yval);
+ }
+ }
+
+ gr_complex
+ dvbt_map_impl::find_constellation_point(int val)
+ {
+ return d_constellation_points[val];
+ }
+
+ void
+ dvbt_map_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ }
+
+ int
+ dvbt_map_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ for (int i = 0; i < (noutput_items * d_nsize); i++) {
+ out[i] = find_constellation_point(in[i]);
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (noutput_items);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_map_impl.h b/gr-dtv/lib/dvbt/dvbt_map_impl.h
new file mode 100644
index 0000000000..045a8e0e6d
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_map_impl.h
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_MAP_IMPL_H
+#define INCLUDED_DTV_DVBT_MAP_IMPL_H
+
+#include <gnuradio/dtv/dvbt_map.h>
+#include "dvbt_configure.h"
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_map_impl : public dvbt_map
+ {
+ private:
+ const dvbt_configure config;
+
+ int d_nsize;
+
+ //Constellation size
+ unsigned char d_constellation_size;
+ // Keeps transmission mode
+ dvbt_transmission_mode_t d_transmission_mode;
+ //Step on each axis of the constellation
+ unsigned char d_step;
+ //Keep Alpha internally
+ unsigned char d_alpha;
+ //Gain for the complex values
+ float d_gain;
+
+ gr_complex * d_constellation_points;
+
+ void make_constellation_points(int size, int step, int alpha);
+ gr_complex find_constellation_point(int val);
+
+ //Return gray representation from natural binary
+ unsigned int bin_to_gray(unsigned int val);
+
+ public:
+ dvbt_map_impl(int nsize, dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvbt_transmission_mode_t transmission, float gain);
+ ~dvbt_map_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_MAP_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon.cc b/gr-dtv/lib/dvbt/dvbt_reed_solomon.cc
new file mode 100644
index 0000000000..6277350b42
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon.cc
@@ -0,0 +1,475 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_reed_solomon.h"
+#include <iostream>
+#include <stdio.h>
+#include <string.h>
+#include <fstream>
+
+using namespace std;
+
+#define min(a,b) ((a) < (b)) ? (a) : (b)
+
+namespace gr {
+ namespace dtv {
+
+ void
+ dvbt_reed_solomon::gf_init(int p, int m, int gfpoly)
+ {
+ d_p = p; d_m = m;
+
+ //maximum number of elements in the GF(p^m)
+ int q = powl(p, m);
+
+ d_gf_exp = new unsigned char[q];
+ if (d_gf_exp == NULL) {
+ std::cout << "Cannot allocate memory for d_gf_exp" << std::endl;
+ return;
+ }
+
+ d_gf_log = new unsigned char[q];
+ if (d_gf_log == NULL) {
+ std::cout << "Cannot allocate memory for d_gf_log" << std::endl;
+ delete [] d_gf_exp;
+ return;
+ }
+
+ int reg_rs = 1;
+
+ d_gf_exp[q - 1] = 0;
+ d_gf_log[0] = q - 1;
+
+ for (int i = 0; i < (q - 1); i++) {
+ d_gf_exp[i] = reg_rs;
+ d_gf_log[reg_rs] = i;
+
+ //This is equvalent with raise to power
+ reg_rs = reg_rs << 1;
+
+ if (reg_rs & (1 << m)) {
+ reg_rs = reg_rs ^ gfpoly;
+ }
+
+ reg_rs = reg_rs & ((1 << m) - 1);
+ }
+ }
+
+ void
+ dvbt_reed_solomon::gf_uninit()
+ {
+ delete [] d_gf_log;
+ delete [] d_gf_exp;
+ }
+
+ int
+ dvbt_reed_solomon::gf_exp(int a)
+ {
+ return d_gf_exp[a % d_n];
+ }
+
+ int
+ dvbt_reed_solomon::gf_log(int a)
+ {
+ return d_gf_log[a % d_n];
+ }
+
+
+ int
+ dvbt_reed_solomon::gf_add(int a, int b)
+ {
+ return (a ^ b);
+ }
+
+ int
+ dvbt_reed_solomon::gf_mul(int a, int b)
+ {
+ if (a == 0 || b == 0) {
+ return 0;
+ }
+ else {
+ return gf_exp(d_gf_log[a] + d_gf_log[b]);
+ }
+ }
+
+ int
+ dvbt_reed_solomon::gf_div(int a, int b)
+ {
+ if (a == 0 || b == 0) {
+ return (0);
+ }
+
+ return (gf_exp(d_n + d_gf_log[a] - d_gf_log[b]));
+ }
+
+ int
+ dvbt_reed_solomon::gf_pow(int a, int power)
+ {
+ if (a == 0) {
+ return (0);
+ }
+
+ return gf_exp(d_n + d_gf_log[a] + power);
+ }
+
+ int
+ dvbt_reed_solomon::gf_lpow(int power)
+ {
+ return d_l[power % d_n];
+ }
+
+ void
+ dvbt_reed_solomon::rs_init(int lambda, int n, int k, int t)
+ {
+ d_n = n; d_k = k; d_t = t;
+ // 2t = n - k, dmin = 2t + 1 = n -k + 1
+
+ d_l = new unsigned char[d_n + 1];
+ if (d_l == NULL) {
+ std::cout << "Cannot allocate memory for d_l" << std::endl;
+ exit(1);
+ }
+
+ d_g = new unsigned char[2 * d_t + 1];
+ if (d_g == NULL) {
+ std::cout << "Cannot allocate memory for d_g" << std::endl;
+ delete [] d_l;
+ exit(1);
+ }
+
+ //Generate roots of lambda
+ d_l[0] = 1;
+
+ for (int i = 1; i <= d_n; i++) {
+ d_l[i] = gf_mul(d_l[i - 1], lambda);
+ }
+
+ //Init Generator polynomial buffer
+ for (int i = 0; i <= (2*t); i++) {
+ d_g[i] = 0;
+ }
+
+ //Start with x+lambda^0
+ d_g[0] = 1;
+
+ //Create generator polynomial
+ for (int i = 1; i <= (2 * t); i++) {
+ for (int j = i; j > 0; j--) {
+ if (d_g[j] != 0) {
+ d_g[j] = gf_add(d_g[j - 1], gf_mul(d_g[j], d_l[i - 1]));
+ }
+ else {
+ d_g[j] = d_g[j - 1];
+ }
+ }
+
+ d_g[0] = gf_mul(d_g[0], d_l[i - 1]);
+ }
+
+ // Init syndrome array
+ d_syn = new unsigned char[2 * d_t + 1];
+ if (d_syn == NULL) {
+ std::cout << "Cannot allocate memory for d_syn" << std::endl;
+ delete [] d_g;
+ delete [] d_l;
+ exit(1);
+ }
+ }
+
+ void
+ dvbt_reed_solomon::rs_uninit()
+ {
+ if (d_syn) {
+ delete [] d_syn;
+ }
+ if (d_g) {
+ delete [] d_g;
+ }
+ if (d_l) {
+ delete [] d_l;
+ }
+ }
+
+ int
+ dvbt_reed_solomon::rs_encode(unsigned char *data_in, unsigned char *parity)
+ {
+ memset(parity, 0, 2 * d_t);
+
+ for (int i = 0; i < d_k; i++) {
+ int feedback = gf_add(data_in[i], parity[0]);
+
+ if (feedback != 0) {
+ for (int j = 1; j < (2 * d_t); j++) {
+ if (d_g[2 * d_t - j] != 0) {
+ parity[j] = gf_add(parity[j], gf_mul(feedback, d_g[2 * d_t - j]));
+ }
+ }
+ }
+
+ //Shift the register
+ memmove(&parity[0], &parity[1], (2 * d_t) - 1);
+
+ if (feedback != 0) {
+ parity[2 * d_t - 1] = gf_mul(feedback, d_g[0]);
+ }
+ else {
+ parity[2 * d_t - 1] = 0;
+ }
+ }
+
+ return (0);
+ }
+
+ int
+ dvbt_reed_solomon::rs_decode(unsigned char *data, unsigned char *eras, const int no_eras)
+ {
+ unsigned char sigma[2 * d_t + 1];
+ unsigned char b[2 * d_t + 1];
+ unsigned char T[2 * d_t + 1];
+ unsigned char reg[2 * d_t + 1];
+ unsigned char root[2 * d_t + 1];
+ unsigned char loc[2 * d_t + 1];
+ unsigned char omega[2 * d_t];
+
+ // Compute erasure locator polynomial
+ memset(sigma, 0, 2 * d_t + 1);
+ sigma[0] = 1;
+
+ if (no_eras > 0) {
+ // In this case we know the locations of errors
+ // Init sigma to be the erasure locator polynomial
+ sigma[1] = gf_exp(d_n-1-eras[0]);
+
+ for (int i = 1; i < no_eras; i++) {
+ int u = d_n-1-eras[i];
+
+ for (int j = i+1; j > 0; j--) {
+ sigma[j] = gf_add(sigma[j], gf_pow(sigma[j - 1], u));
+ }
+ }
+ }
+
+ // Calculate syndrome
+
+ for (int j = 0; j < 2 * d_t; j++) {
+ d_syn[j] = data[0];
+ }
+
+ for (int j = 1; j < d_n; j++) {
+ for (int i = 0; i < 2 * d_t; i++) {
+ d_syn[i] = gf_add(data[j], gf_pow(d_syn[i], i));
+ }
+ }
+
+ int syn_error = 0;
+
+ // Verify all syndromes
+ for (int i = 0; i < 2 * d_t; i++) {
+ syn_error |= d_syn[i];
+ }
+
+ if (!syn_error) {
+ // The syndrome is a codeword
+ // Return data unmodified
+ return (0);
+ }
+
+ // Use Modified (errors+erasures) BMA. Algorithm of Berlekamp-Massey
+ // S(i)=r(lambda^i)=e(lambda^i)
+
+ int r = no_eras;
+ int el = no_eras;
+
+ memcpy(b, sigma, 2 * d_t + 1);
+
+ while (++r <= 2 * d_t) {
+ int d_discr = 0;
+
+ for (int i = 0; i < r; i++) {
+ d_discr = gf_add(d_discr, gf_mul(sigma[i], d_syn[r - i - 1]));
+ }
+
+ if (d_discr == 0) {
+ // b(x) = x * b(x)
+ memmove(&b[1], b, 2 * d_t);
+ b[0] = 0;
+ }
+ else {
+ T[0] = sigma[0];
+
+ // T(x) = sigma(x) + d*x*b(x)
+ for (int i = 0; i < 2 * d_t; i++) {
+ T[i + 1] = gf_add(sigma[i + 1], gf_mul(d_discr, b[i]));
+ }
+
+ if (2 * el <= r + no_eras - 1) {
+ el = r + no_eras - el;
+
+ // b(i) = sigma(i) / discr
+ for (int i = 0; i <= 2 * d_t; i++) {
+ b[i] = gf_div(sigma[i], d_discr);
+ }
+ }
+ else {
+ // b(x) = x*b(x)
+ memmove(&b[1], b, 2 * d_t);
+ b[0] = 0;
+ }
+ memcpy(sigma, T, 2 * d_t + 1);
+ }
+ }
+
+ // Compute degree(sigma)
+ int deg_sigma = 0;
+
+ for (int i = 0; i < 2 * d_t + 1; i++) {
+ if (sigma[i] != 0) {
+ deg_sigma = i;
+ }
+ }
+
+ // Find the roots of sigma(x) by Chien search
+ // Test sum(1)=1+sigma(1)*(lambda^1)+...+sigma(nu)*lambda(^nu)
+ // Test sum(2)=1+sigma(1)*(lambda^2)+...+sigma(nu)*lambda(^nu*2)
+ // ...
+ // Test sum(l)=1+sigma(1)*(lambda^l)+...+sigma(nu)*lambda(^nu*l)
+ // in order to see if lambda^(-1) is a root
+ // where nu is degree(sigma)
+
+ int no_roots = 0;
+
+ memcpy(&reg[1], &sigma[1], 2 * d_t);
+
+ for (int i = 1; i <= d_n; i++) {
+ int q = 1;
+
+ for (int j = deg_sigma; j > 0; j--) {
+ reg[j] = gf_pow(reg[j], j);
+ q = gf_add(q, reg[j]);
+ }
+
+ if (q != 0) {
+ continue;
+ }
+
+ // We are here when we found roots of the sigma(x)
+ // Keep roots in index form
+ root[no_roots] = i;
+ loc[no_roots] = i - 1;
+
+ if (++no_roots == deg_sigma) {
+ break;
+ }
+ }
+
+ if (no_roots != deg_sigma) {
+ // Uncorrectable error detected
+ if (eras) {
+ for (int i = 0; i < no_roots; i++)
+ eras[i] = loc[i];
+ }
+
+ return (-1);
+ }
+
+ // Compute erros+erasures evaluator polynomial
+ // omega(x)=sigma(x)S(x) mod (x ^ 2 * t)
+ int deg_omega = 0;
+
+ for (int i = 0; i < 2 * d_t; i++) {
+ int tmp = 0;
+ int j = (deg_sigma < i) ? deg_sigma : i;
+
+ for(;j >= 0; j--) {
+ tmp = gf_add(tmp, gf_mul(d_syn[i - j], sigma[j]));
+ }
+
+ if(tmp != 0) {
+ deg_omega = i;
+ }
+
+ omega[i] = tmp;
+ }
+ omega[2 * d_t] = 0;
+
+ // Compute error values using Forney formula (poly form)
+ // e(j(l))) = (lambda(j(l)) ^ 2) * omega(lambda ^ (-j(l))) / sigma_pr(lambda ^ (-j(l)))
+ // where sigma_pr is the formal derivative of sigma
+
+ for (int j = no_roots - 1; j >= 0; j--) {
+ int num1 = 0;
+
+ // roots[] are in index form
+ for (int i = deg_omega; i >= 0; i--) {
+ num1 = gf_add(num1, gf_pow(omega[i], i * root[j]));
+ }
+
+ // root[] is in index form
+ int num2 = gf_exp(root[j] * (-1) + d_n);
+
+ int den = 0;
+
+ // sigma[i+1] for i even is the formal derivative lambda_pr of sigma[i]
+ int deg_max = min(deg_sigma, 2 * d_t - 1);
+
+ for (int i = 1; i <= deg_max; i += 2) {
+ if (sigma[i] != 0)
+ den = gf_add(den, gf_exp(d_gf_log[sigma[i]] + (i - 1) * root[j]));
+ }
+
+ if (den == 0) {
+ if (eras) {
+ for (int i = 0; i < no_roots; i++) {
+ eras[i] = loc[i];
+ }
+ }
+ return (-1);
+ }
+
+ int err = gf_div(gf_mul(num1, num2), den);
+
+ data[loc[j]] = gf_add(data[loc[j]], err);
+ }
+
+ return(no_roots);
+ }
+
+
+ dvbt_reed_solomon::dvbt_reed_solomon(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks):
+ d_p(p), d_m(m), d_gfpoly(gfpoly), d_n(n), d_k(k), d_t(t), d_s(s), d_blocks(blocks)
+ {
+ gf_init(d_p, d_m, d_gfpoly);
+ rs_init(d_p, d_n, d_k, d_t);
+ }
+
+ dvbt_reed_solomon::~dvbt_reed_solomon()
+ {
+ rs_uninit();
+ gf_uninit();
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon.h b/gr-dtv/lib/dvbt/dvbt_reed_solomon.h
new file mode 100644
index 0000000000..b9286d0ffd
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon.h
@@ -0,0 +1,70 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_REED_SOLOMON_H
+#define INCLUDED_DTV_DVBT_REED_SOLOMON_H
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_reed_solomon
+ {
+ private:
+ int d_p;
+ int d_m;
+ int d_gfpoly;
+ int d_n;
+ int d_k;
+ int d_t;
+ int d_s;
+ int d_blocks;
+ unsigned char *d_gf_exp;
+ unsigned char *d_gf_log;
+ unsigned char *d_l;
+ unsigned char *d_g;
+
+ unsigned char *d_syn;
+
+ int gf_add(int a, int b);
+ int gf_mul(int a, int b);
+ int gf_div(int a, int b);
+ int gf_exp(int a);
+ int gf_log(int a);
+ int gf_pow(int a, int power);
+ int gf_lpow(int power);
+
+ void gf_init(int p, int m, int gfpoly);
+ void gf_uninit();
+ void rs_init(int lambda, int n, int k, int t);
+ void rs_uninit();
+
+ public:
+ int rs_encode(unsigned char *data, unsigned char *parity);
+ int rs_decode(unsigned char *data, unsigned char *eras, const int no_eras);
+
+ dvbt_reed_solomon(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks);
+ ~dvbt_reed_solomon();
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.cc b/gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.cc
new file mode 100644
index 0000000000..561ea08ded
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.cc
@@ -0,0 +1,103 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_reed_solomon_enc_impl.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace dtv {
+
+ dvbt_reed_solomon_enc::sptr
+ dvbt_reed_solomon_enc::make(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_reed_solomon_enc_impl(p, m, gfpoly, n, k, t, s, blocks));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_reed_solomon_enc_impl::dvbt_reed_solomon_enc_impl(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks)
+ : block("dvbt_reed_solomon",
+ io_signature::make(1, 1, sizeof(unsigned char) * blocks * (k - s)),
+ io_signature::make(1, 1, sizeof(unsigned char) * blocks * (n - s))),
+ d_p(p), d_m(m), d_gfpoly(gfpoly), d_n(n), d_k(k), d_t(t), d_s(s), d_blocks(blocks),
+ d_rs(p, m, gfpoly, n, k, t, s, blocks)
+ {
+ d_in = new unsigned char[d_n];
+ if (d_in == NULL) {
+ std::cout << "Cannot allocate memory for d_in" << std::endl;
+ return;
+ }
+ memset(&d_in[0], 0, d_n);
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_reed_solomon_enc_impl::~dvbt_reed_solomon_enc_impl()
+ {
+ delete [] d_in;
+ }
+
+ void
+ dvbt_reed_solomon_enc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ }
+
+ int
+ dvbt_reed_solomon_enc_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (const unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ int in_bsize = d_k - d_s;
+ int out_bsize = d_n - d_s;
+
+ // We get a superblock of d_blocks blocks
+ for (int i = 0; i < (d_blocks * noutput_items); i++) {
+ //TODO - zero copy between in/out ?
+ memcpy(&d_in[d_s], &in[i * in_bsize], in_bsize);
+
+ d_rs.rs_encode(&d_in[0], &d_in[d_k]);
+
+ memcpy(&out[i * out_bsize], &d_in[d_s], out_bsize);
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (noutput_items);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.h b/gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.h
new file mode 100644
index 0000000000..669ee2761a
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_reed_solomon_enc_impl.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_REED_SOLOMON_ENC_IMPL_H
+#define INCLUDED_DTV_DVBT_REED_SOLOMON_ENC_IMPL_H
+
+#include <gnuradio/dtv/dvbt_reed_solomon_enc.h>
+#include "dvbt_reed_solomon.h"
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_reed_solomon_enc_impl : public dvbt_reed_solomon_enc
+ {
+ private:
+ int d_p;
+ int d_m;
+ int d_gfpoly;
+ int d_n;
+ int d_k;
+ int d_t;
+ int d_s;
+ int d_blocks;
+
+ unsigned char * d_in;
+
+ dvbt_reed_solomon d_rs;
+
+ public:
+ dvbt_reed_solomon_enc_impl(int p, int m, int gfpoly, int n, int k, int t, int s, int blocks);
+ ~dvbt_reed_solomon_enc_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_REED_SOLOMON_ENC_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc
new file mode 100644
index 0000000000..58fc76c64e
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.cc
@@ -0,0 +1,1284 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_reference_signals_impl.h"
+#include <complex>
+#include <stdio.h>
+#include <gnuradio/expj.h>
+#include <gnuradio/math.h>
+
+namespace gr {
+ namespace dtv {
+
+ //Number of symbols in a frame
+ const int dvbt_pilot_gen::d_symbols_per_frame = SYMBOLS_PER_FRAME;
+ //Number of frames in a superframe
+ const int dvbt_pilot_gen::d_frames_per_superframe = FRAMES_PER_SUPERFRAME;
+
+ // 2k mode
+ // Scattered pilots # of carriers
+ const int dvbt_pilot_gen::d_spilot_carriers_size_2k = SCATTERED_PILOT_SIZE_2k;
+ // Continual pilots # of carriers and positions
+ const int dvbt_pilot_gen::d_cpilot_carriers_size_2k = CONTINUAL_PILOT_SIZE_2k;
+ const int dvbt_pilot_gen::d_cpilot_carriers_2k[dvbt_pilot_gen::d_cpilot_carriers_size_2k] = {
+ 0, 48, 54, 87, 141, 156, 192, \
+ 201, 255, 279, 282, 333, 432, 450, \
+ 483, 525, 531, 618, 636, 714, 759, \
+ 765, 780, 804, 873, 888, 918, 939, \
+ 942, 969, 984, 1050, 1101, 1107, 1110, \
+ 1137, 1140, 1146, 1206, 1269, 1323, 1377, \
+ 1491, 1683, 1704
+ };
+ // TPS pilots # of carriers and positions
+ const int dvbt_pilot_gen::d_tps_carriers_size_2k = TPS_PILOT_SIZE_2k;
+ const int dvbt_pilot_gen::d_tps_carriers_2k[dvbt_pilot_gen::d_tps_carriers_size_2k] = {
+ 34, 50, 209, 346, 413, \
+ 569, 595, 688, 790, 901, \
+ 1073, 1219, 1262, 1286, 1469, \
+ 1594, 1687
+ };
+
+ // 8k mode
+ // Scattered pilots # of carriers
+ const int dvbt_pilot_gen::d_spilot_carriers_size_8k = SCATTERED_PILOT_SIZE_8k;
+ // Continual pilots # of carriers and positions
+ const int dvbt_pilot_gen::d_cpilot_carriers_size_8k = CONTINUAL_PILOT_SIZE_8k;
+ const int dvbt_pilot_gen::d_cpilot_carriers_8k[dvbt_pilot_gen::d_cpilot_carriers_size_8k] = {
+ 0, 48, 54, 87, 141, 156, 192,
+ 201, 255, 279, 282, 333, 432, 450,
+ 483, 525, 531, 618, 636, 714, 759,
+ 765, 780, 804, 873, 888, 918, 939,
+ 942, 969, 984, 1050, 1101, 1107, 1110,
+ 1137, 1140, 1146, 1206, 1269, 1323, 1377,
+ 1491, 1683, 1704, 1752, 1758, 1791, 1845,
+ 1860, 1896, 1905, 1959, 1983, 1986, 2037,
+ 2136, 2154, 2187, 2229, 2235, 2322, 2340,
+ 2418, 2463, 2469, 2484, 2508, 2577, 2592,
+ 2622, 2643, 2646, 2673, 2688, 2754, 2805,
+ 2811, 2814, 2841, 2844, 2850, 2910, 2973,
+ 3027, 3081, 3195, 3387, 3408, 3456, 3462,
+ 3495, 3549, 3564, 3600, 3609, 3663, 3687,
+ 3690, 3741, 3840, 3858, 3891, 3933, 3939,
+ 4026, 4044, 4122, 4167, 4173, 4188, 4212,
+ 4281, 4296, 4326, 4347, 4350, 4377, 4392,
+ 4458, 4509, 4515, 4518, 4545, 4548, 4554,
+ 4614, 4677, 4731, 4785, 4899, 5091, 5112,
+ 5160, 5166, 5199, 5253, 5268, 5304, 5313,
+ 5367, 5391, 5394, 5445, 5544, 5562, 5595,
+ 5637, 5643, 5730, 5748, 5826, 5871, 5877,
+ 5892, 5916, 5985, 6000, 6030, 6051, 6054,
+ 6081, 6096, 6162, 6213, 6219, 6222, 6249,
+ 6252, 6258, 6318, 6381, 6435, 6489, 6603,
+ 6795, 6816
+ };
+ // TPS pilots # of carriers and positions
+ const int dvbt_pilot_gen::d_tps_carriers_size_8k = TPS_PILOT_SIZE_8k;
+ const int dvbt_pilot_gen::d_tps_carriers_8k[dvbt_pilot_gen::d_tps_carriers_size_8k] = {
+ 34, 50, 209, 346, 413, 569, 595, 688, \
+ 790, 901, 1073, 1219, 1262, 1286, 1469, 1594, \
+ 1687, 1738, 1754, 1913, 2050, 2117, 2273, 2299, \
+ 2392, 2494, 2605, 2777, 2923, 2966, 2990, 3173, \
+ 3298, 3391, 3442, 3458, 3617, 3754, 3821, 3977, \
+ 4003, 4096, 4198, 4309, 4481, 4627, 4670, 4694, \
+ 4877, 5002, 5095, 5146, 5162, 5321, 5458, 5525, \
+ 5681, 5707, 5800, 5902, 6013, 6185, 6331, 6374, \
+ 6398, 6581, 6706, 6799
+ };
+
+ // TPS sync sequence for odd and even frames
+ const int dvbt_pilot_gen::d_tps_sync_size = 16; // TODO
+ const int dvbt_pilot_gen::d_tps_sync_even[d_tps_sync_size] = {
+ 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0
+ };
+ const int dvbt_pilot_gen::d_tps_sync_odd[d_tps_sync_size] = {
+ 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1
+ };
+
+ /*
+ * Constructor of class
+ */
+ dvbt_pilot_gen::dvbt_pilot_gen(const dvbt_configure &c) : config(c),
+ d_spilot_index(0),
+ d_cpilot_index(0),
+ d_tpilot_index(0),
+ d_symbol_index(0),
+ d_symbol_index_known(0),
+ d_frame_index(0),
+ d_superframe_index(0),
+ d_freq_offset_max(8),
+ d_trigger_index(0),
+ d_payload_index(0),
+ d_chanestim_index(0),
+ d_prev_mod_symbol_index(0),
+ d_mod_symbol_index(0)
+ {
+ //Determine parameters from config file
+ d_Kmin = config.d_Kmin;
+ d_Kmax = config.d_Kmax;
+ d_fft_length = config.d_fft_length;
+ d_payload_length = config.d_payload_length;
+ d_zeros_on_left = config.d_zeros_on_left;
+ d_zeros_on_right = config.d_zeros_on_right;
+ d_cp_length = config.d_cp_length;
+
+ //Set-up pilot data depending on transmission mode
+ if (config.d_transmission_mode == T2k) {
+ d_spilot_carriers_size = d_spilot_carriers_size_2k;
+ d_cpilot_carriers_size = d_cpilot_carriers_size_2k;
+ d_cpilot_carriers = d_cpilot_carriers_2k;
+ d_tps_carriers_size = d_tps_carriers_size_2k;
+ d_tps_carriers = d_tps_carriers_2k;
+ }
+ else if (config.d_transmission_mode == T8k) {
+ d_spilot_carriers_size = d_spilot_carriers_size_8k;
+ d_cpilot_carriers_size = d_cpilot_carriers_size_8k;
+ d_cpilot_carriers = d_cpilot_carriers_8k;
+ d_tps_carriers_size = d_tps_carriers_size_8k;
+ d_tps_carriers = d_tps_carriers_8k;
+ }
+ else {
+ d_spilot_carriers_size = d_spilot_carriers_size_2k;
+ d_cpilot_carriers_size = d_cpilot_carriers_size_2k;
+ d_cpilot_carriers = d_cpilot_carriers_2k;
+ d_tps_carriers_size = d_tps_carriers_size_2k;
+ d_tps_carriers = d_tps_carriers_2k;
+ }
+
+ d_freq_offset = 0;
+ d_carrier_freq_correction = 0.0;
+ d_sampling_freq_correction = 0.0;
+
+ //allocate PRBS buffer
+ d_wk = new char[d_Kmax - d_Kmin + 1];
+ if (d_wk == NULL) {
+ std::cout << "Cannot allocate memory for d_wk" << std::endl;
+ exit(1);
+ }
+ // Generate wk sequence
+ generate_prbs();
+
+ // allocate buffer for scattered pilots
+ d_spilot_carriers_val = new gr_complex[d_Kmax - d_Kmin + 1];
+ if (d_spilot_carriers_val == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // allocate buffer for channel gains (for each useful carrier)
+ d_channel_gain = new gr_complex[d_Kmax - d_Kmin + 1];
+ if (d_channel_gain == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // Allocate buffer for continual pilots phase diffs
+ d_known_phase_diff = new float[d_cpilot_carriers_size - 1];
+ if (d_known_phase_diff == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // Obtain phase diff for all continual pilots
+ for (int i = 0; i < (d_cpilot_carriers_size - 1); i++) {
+ d_known_phase_diff[i] = \
+ norm(get_cpilot_value(d_cpilot_carriers[i + 1]) - get_cpilot_value(d_cpilot_carriers[i]));
+ }
+
+ d_cpilot_phase_diff = new float[d_cpilot_carriers_size - 1];
+ if (d_cpilot_phase_diff == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // Allocate buffer for derotated input symbol
+ d_derot_in = new gr_complex[d_fft_length];
+ if (d_derot_in == NULL) {
+ std::cout << "Cannot allocate memory for d_derot_in" << std::endl;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // allocate buffer for first tps symbol constellation
+ d_tps_carriers_val = new gr_complex[d_tps_carriers_size];
+ if (d_tps_carriers_val == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_carriers_val" << std::endl;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // allocate tps data buffer
+ d_tps_data = new unsigned char[d_symbols_per_frame];
+ if (d_tps_data == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_data" << std::endl;
+ delete [] d_tps_carriers_val;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ d_prev_tps_symbol = new gr_complex[d_tps_carriers_size];
+ if (d_prev_tps_symbol == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_data" << std::endl;
+ delete [] d_tps_data;
+ delete [] d_tps_carriers_val;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+ memset(d_prev_tps_symbol, 0, d_tps_carriers_size * sizeof(gr_complex));
+
+ d_tps_symbol = new gr_complex[d_tps_carriers_size];
+ if (d_tps_symbol == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_data" << std::endl;
+ delete [] d_prev_tps_symbol;
+ delete [] d_tps_data;
+ delete [] d_tps_carriers_val;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+ memset(d_tps_symbol, 0, d_tps_carriers_size * sizeof(gr_complex));
+
+ // Init receive TPS data vector
+ for (int i = 0; i < d_symbols_per_frame; i++) {
+ d_rcv_tps_data.push_back(0);
+ }
+
+ // Init TPS sync sequence
+ for (int i = 0; i < d_tps_sync_size; i++) {
+ d_tps_sync_evenv.push_back(d_tps_sync_even[i]);
+ d_tps_sync_oddv.push_back(d_tps_sync_odd[i]);
+ }
+
+ // Allocate buffer for channel estimation carriers
+ d_chanestim_carriers = new int[d_Kmax - d_Kmin + 1];
+ if (d_chanestim_carriers == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_data" << std::endl;
+ delete [] d_tps_symbol;
+ delete [] d_prev_tps_symbol;
+ delete [] d_tps_data;
+ delete [] d_tps_carriers_val;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // Allocate buffer for payload carriers
+ d_payload_carriers = new int[d_Kmax - d_Kmin + 1];
+ if (d_payload_carriers == NULL) {
+ std::cout << "Cannot allocate memory for d_tps_data" << std::endl;
+ delete [] d_chanestim_carriers;
+ delete [] d_tps_symbol;
+ delete [] d_prev_tps_symbol;
+ delete [] d_tps_data;
+ delete [] d_tps_carriers_val;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ exit(1);
+ }
+
+ // Reset the pilot generator
+ reset_pilot_generator();
+ // Format TPS data with current values
+ format_tps_data();
+ }
+
+ /*
+ * Destructor of class
+ */
+ dvbt_pilot_gen::~dvbt_pilot_gen()
+ {
+ delete [] d_payload_carriers;
+ delete [] d_chanestim_carriers;
+ delete [] d_tps_symbol;
+ delete [] d_prev_tps_symbol;
+ delete [] d_tps_data;
+ delete [] d_tps_carriers_val;
+ delete [] d_derot_in;
+ delete [] d_cpilot_phase_diff;
+ delete [] d_known_phase_diff;
+ delete [] d_channel_gain;
+ delete [] d_spilot_carriers_val;
+ delete [] d_wk;
+ }
+
+ /*
+ * Generate PRBS sequence
+ * X^11 + X^2 + 1
+ * en 300 744 - section 4.5.2
+ */
+ void
+ dvbt_pilot_gen::generate_prbs()
+ {
+ // init PRBS register with 1s
+ unsigned int reg_prbs = (1 << 11) - 1;
+
+ for (int k = 0; k < (d_Kmax - d_Kmin + 1); k++) {
+ d_wk[k] = (char)(reg_prbs & 0x01);
+ int new_bit = ((reg_prbs >> 2) ^ (reg_prbs >> 0)) & 0x01;
+ reg_prbs = (reg_prbs >> 1) | (new_bit << 10);
+ }
+ }
+
+ /*
+ * Generate shortened BCH(67, 53) codes from TPS data
+ * Extend the code with 60 bits and use BCH(127, 113)
+ */
+ void
+ dvbt_pilot_gen::generate_bch_code()
+ {
+ //TODO
+ //DO other way: if (feedback == 1) reg = reg ^ polymomial
+ //else nothing
+
+ //(n, k) = (127, 113) = (60+67, 60+53)
+ unsigned int reg_bch = 0;
+ unsigned char data_in[113];
+
+ //fill in 60 zeros
+ memset(&data_in[0], 0, 60);
+ //fill in TPS data - start bit not included
+ memcpy(&data_in[60], &d_tps_data[1], 53);
+
+ //X^14+X^9+X^8+X^6+X^5+X^4+X^2+X+1
+ for (int i = 0; i < 113; i++) {
+ int feedback = 0x1 & (data_in[i] ^ reg_bch);
+ reg_bch = reg_bch >> 1;
+ reg_bch |= feedback << 13;
+ reg_bch = reg_bch \
+ ^ (feedback << 12) ^ (feedback << 11) \
+ ^ (feedback << 9) ^ (feedback << 8) \
+ ^ (feedback << 7) ^ (feedback << 5) \
+ ^ (feedback << 4);
+ }
+
+ for (int i = 0; i < 14; i++) {
+ d_tps_data[i + 54] = 0x1 & (reg_bch >> i);
+ }
+ }
+
+ int
+ dvbt_pilot_gen::verify_bch_code(std::deque<char> data)
+ {
+ int ret = 0;
+
+ //TODO
+ //DO other way: if (feedback == 1) reg = reg ^ polymomial
+ //else nothing
+
+ //(n, k) = (127, 113) = (60+67, 60+53)
+ unsigned int reg_bch = 0;
+ unsigned char data_in[113];
+
+ //fill in 60 zeros
+ memset(&data_in[0], 0, 60);
+ //fill in TPS data - start bit not included
+ //memcpy(&data_in[60], &data[1], 53);
+ for (int i = 0; i < 53; i++)
+ data_in[60 + i] = data[1 + i];
+
+ //X^14+X^9+X^8+X^6+X^5+X^4+X^2+X+1
+ for (int i = 0; i < 113; i++) {
+ int feedback = 0x1 & (data_in[i] ^ reg_bch);
+ reg_bch = reg_bch >> 1;
+ reg_bch |= feedback << 13;
+ reg_bch = reg_bch \
+ ^ (feedback << 12) ^ (feedback << 11) \
+ ^ (feedback << 9) ^ (feedback << 8) \
+ ^ (feedback << 7) ^ (feedback << 5) \
+ ^ (feedback << 4);
+ }
+
+ for (int i = 0; i < 14; i++) {
+ if ((unsigned int)data[i + 54] != (0x1 & (reg_bch >> i))) {
+ ret = -1;
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ void
+ dvbt_pilot_gen::set_symbol_index(int sindex)
+ {
+ d_symbol_index = sindex;
+ }
+
+ int
+ dvbt_pilot_gen::get_symbol_index()
+ {
+ return d_symbol_index;
+ }
+
+ void
+ dvbt_pilot_gen::set_tps_data()
+ {
+ }
+
+ void
+ dvbt_pilot_gen::get_tps_data()
+ {
+ }
+
+ /*
+ * Reset pilot generator
+ */
+ void
+ dvbt_pilot_gen::reset_pilot_generator()
+ {
+ d_spilot_index = 0; d_cpilot_index = 0; d_tpilot_index = 0;
+ d_payload_index = 0; d_chanestim_index = 0;
+ d_symbol_index = 0; d_frame_index = 0; d_superframe_index = 0;
+ d_symbol_index_known = 0;
+ d_equalizer_ready = 0;
+ }
+
+ /*
+ * Init scattered pilot generator
+ */
+ int
+ dvbt_pilot_gen::get_current_spilot(int sindex) const
+ {
+ //TODO - can be optimized for same symbol_index
+ return (d_Kmin + 3 * (sindex % 4) + 12 * d_spilot_index);
+ }
+
+ gr_complex
+ dvbt_pilot_gen::get_spilot_value(int spilot)
+ {
+ // TODO - can be calculated at the beginning
+ return gr_complex(4 * 2 * (0.5 - d_wk[spilot]) / 3, 0);
+ }
+
+ void
+ dvbt_pilot_gen::set_spilot_value(int spilot, gr_complex val)
+ {
+ d_spilot_carriers_val[spilot] = val;
+ }
+
+ void
+ dvbt_pilot_gen::set_channel_gain(int spilot, gr_complex val)
+ {
+ // Gain gval=rxval/txval
+ d_channel_gain[spilot] = gr_complex((4 * 2 * (0.5 - d_wk[spilot]) / 3), 0) / val;
+ }
+ void
+ dvbt_pilot_gen::advance_spilot(int sindex)
+ {
+ //TODO - do in a simpler way?
+ int size = d_spilot_carriers_size;
+
+ if (sindex == 0) {
+ size = d_spilot_carriers_size + 1;
+ }
+
+ // TODO - fix this - what value should we use?
+ ++d_spilot_index;
+ d_spilot_index = d_spilot_index % size;
+ }
+
+ int
+ dvbt_pilot_gen::get_first_spilot()
+ {
+ d_spilot_index = 0;
+
+ return (d_Kmin + 3 * (d_symbol_index % 4));
+ }
+
+ int
+ dvbt_pilot_gen::get_last_spilot() const
+ {
+ int size = d_spilot_carriers_size - 1;
+
+ if (d_symbol_index == 0) {
+ size = d_spilot_carriers_size;
+ }
+
+ return (d_Kmin + 3 * (d_symbol_index % 4) + 12 * size);
+ }
+
+ int
+ dvbt_pilot_gen::get_next_spilot()
+ {
+ int pilot = (d_Kmin + 3 * (d_symbol_index % 4) + 12 * (++d_spilot_index));
+
+ if (pilot > d_Kmax) {
+ pilot = d_Kmax;
+ }
+
+ return pilot;
+ }
+
+ int
+ dvbt_pilot_gen::process_spilot_data(const gr_complex * in)
+ {
+ // This is channel estimator
+ // Interpolate the gain between carriers to obtain
+ // gain for non pilot carriers - we use linear interpolation
+
+ /*************************************************************/
+ // Find out the OFDM symbol index (value 0 to 3) sent
+ // in current block by correlating scattered symbols with
+ // current block - result is (symbol index % 4)
+ /*************************************************************/
+ float max = 0; float sum = 0;
+
+ for (int scount = 0; scount < 4; scount++) {
+ d_spilot_index = 0; d_cpilot_index = 0;
+ d_chanestim_index = 0;
+
+ for (int k = 0; k < (d_Kmax - d_Kmin + 1); k++) {
+ // Keep data for channel estimation
+ if (k == get_current_spilot(scount)) {
+ set_chanestim_carrier(k);
+ advance_spilot(scount);
+ advance_chanestim();
+ }
+ }
+
+ gr_complex c = gr_complex(0.0, 0.0);
+
+ // This should be of range 0 to d_chanestim_index bit for now we use just a
+ // small number of spilots to obtain the symbol index
+ for (int j = 0; j < 10; j++) {
+ c += get_spilot_value(d_chanestim_carriers[j]) * conj(in[d_zeros_on_left + d_chanestim_carriers[j]]);
+ }
+ sum = norm(c);
+
+ if (sum > max) {
+ max = sum;
+ d_mod_symbol_index = scount;
+ }
+ }
+
+ /*************************************************************/
+ // Keep data for channel estimator
+ // This method interpolates scattered measurements across one OFDM symbol
+ // It does not use measurements from the previous OFDM symbols (does not use history)
+ // as it may have encountered a phase change for the current phase only
+ /*************************************************************/
+
+ d_spilot_index = 0; d_cpilot_index = 0;
+ d_chanestim_index = 0;
+
+ for (int k = 0; k < (d_Kmax - d_Kmin + 1); k++) {
+ // Keep data for channel estimation
+ if (k == get_current_spilot(d_mod_symbol_index)) {
+ set_chanestim_carrier(k);
+ advance_spilot(d_mod_symbol_index);
+ advance_chanestim();
+ }
+
+ // Keep data for channel estimation
+ if (k == get_current_cpilot()) {
+ set_chanestim_carrier(k);
+ advance_cpilot();
+ advance_chanestim();
+ }
+ }
+
+ // We use both scattered pilots and continual pilots
+ for (int i = 0, startk = d_chanestim_carriers[0]; i < d_chanestim_index; i++) {
+ // Get a carrier from the list of carriers
+ // used for channel estimation
+ int k = d_chanestim_carriers[i];
+
+ set_channel_gain(k, in[k + d_zeros_on_left]);
+
+ // Calculate tg(alpha) due to linear interpolation
+ gr_complex tg_alpha = (d_channel_gain[k] - d_channel_gain[startk]) / gr_complex(11.0, 0.0);
+
+ // Calculate interpolation for all intermediate values
+ for (int j = 1; j < (k - startk); j++) {
+ gr_complex current = d_channel_gain[startk] + tg_alpha * gr_complex(j, 0.0);
+ d_channel_gain[startk + j] = current;
+ }
+
+ startk = k;
+ }
+
+ // Signal that equalizer is ready
+ d_equalizer_ready = 1;
+
+ int diff_sindex = (d_mod_symbol_index - d_prev_mod_symbol_index + 4) % 4;
+
+ d_prev_mod_symbol_index = d_mod_symbol_index;
+
+ return diff_sindex;
+ }
+
+ /*
+ * Init continual pilot generator
+ */
+ int
+ dvbt_pilot_gen::get_current_cpilot() const
+ {
+ return d_cpilot_carriers[d_cpilot_index];
+ }
+
+ gr_complex
+ dvbt_pilot_gen::get_cpilot_value(int cpilot)
+ {
+ //TODO - can be calculated at the beginning
+ return gr_complex((float)(4 * 2 * (0.5 - d_wk[cpilot])) / 3, 0);
+ }
+
+ void
+ dvbt_pilot_gen::advance_cpilot()
+ {
+ ++d_cpilot_index;
+ d_cpilot_index = d_cpilot_index % d_cpilot_carriers_size;
+ }
+
+ void
+ dvbt_pilot_gen::process_cpilot_data(const gr_complex * in)
+ {
+ // Look for maximum correlation for cpilots
+ // in order to obtain post FFT integer frequency correction
+
+ float max = 0; float sum = 0;
+ int start = 0;
+ float phase;
+
+ for (int i = d_zeros_on_left - d_freq_offset_max; i < d_zeros_on_left + d_freq_offset_max; i++) {
+ sum = 0;
+ for (int j = 0; j < (d_cpilot_carriers_size - 1); j++) {
+ phase = norm(in[i + d_cpilot_carriers[j + 1]] - in[i + d_cpilot_carriers[j]]);
+ sum += d_known_phase_diff[j] * phase;
+ }
+
+ if (sum > max) {
+ max = sum;
+ start = i;
+ }
+ }
+
+ d_freq_offset = start - d_zeros_on_left;
+ }
+
+ void
+ dvbt_pilot_gen::compute_oneshot_csft(const gr_complex * in)
+ {
+ gr_complex left_corr_sum = 0.0; gr_complex right_corr_sum = 0.0;
+ int half_size = (d_cpilot_carriers_size - 1) / 2;
+
+ // TODO init this in constructor
+ float carrier_coeff = 1.0 / (2 * M_PI * (1 + float (d_cp_length) / float (d_fft_length)) * 2);
+ float sampling_coeff = 1.0 / (2 * M_PI * ((1 + float (d_cp_length) / float (d_fft_length)) * ((float)d_cpilot_carriers_size / 2.0)));
+
+ float left_angle, right_angle;
+
+ // Compute cpilots correlation between previous symbol and current symbol
+ // in both halves of the cpilots. The cpilots are distributed evenly
+ // on left and right sides of the center frequency.
+
+ for (int j = 0; j < half_size; j++) {
+ left_corr_sum += in[d_freq_offset + d_zeros_on_left + d_cpilot_carriers[j]] * \
+ std::conj(in[d_freq_offset + d_fft_length + d_zeros_on_left + d_cpilot_carriers[j]]);
+ }
+
+ for (int j = half_size + 1; j < d_cpilot_carriers_size; j++) {
+ right_corr_sum += in[d_freq_offset + d_zeros_on_left + d_cpilot_carriers[j]] * \
+ std::conj(in[d_freq_offset + d_fft_length + d_zeros_on_left + d_cpilot_carriers[j]]);
+ }
+
+ left_angle = std::arg(left_corr_sum);
+ right_angle = std::arg(right_corr_sum);
+
+ d_carrier_freq_correction = (right_angle + left_angle) * carrier_coeff;
+ d_sampling_freq_correction = (right_angle - left_angle) * sampling_coeff;
+ }
+
+ gr_complex *
+ dvbt_pilot_gen::frequency_correction(const gr_complex * in, gr_complex * out)
+ {
+ // TODO - use PI control loop to calculate tracking corrections
+ int symbol_count = 1;
+
+ for (int k = 0; k < d_fft_length; k++) {
+ // TODO - for 2k mode the continuous pilots are not split evenly
+ // between left/right center frequency. Probably the scattered
+ // pilots needs to be added.
+
+ float correction = (float)d_freq_offset + d_carrier_freq_correction;
+
+ gr_complex c = gr_expj(-2 * M_PI * correction * \
+ (d_fft_length + d_cp_length) / d_fft_length * symbol_count);
+
+ // TODO - vectorize this operation
+ out[k] = c * in[k + d_freq_offset];
+ }
+
+ return (out);
+ }
+
+ /*
+ * Init tps sequence, return values for first position
+ * If first symbol then init tps DBPSK data
+ */
+ int
+ dvbt_pilot_gen::get_current_tpilot() const
+ {
+ return d_tps_carriers[d_tpilot_index];
+ }
+
+ gr_complex
+ dvbt_pilot_gen::get_tpilot_value(int tpilot)
+ {
+ //TODO - it can be calculated at the beginnning
+ if (d_symbol_index == 0) {
+ d_tps_carriers_val[d_tpilot_index] = gr_complex(2 * (0.5 - d_wk[tpilot]), 0);
+ }
+ else {
+ if (d_tps_data[d_symbol_index] == 1) {
+ d_tps_carriers_val[d_tpilot_index] = gr_complex(-d_tps_carriers_val[d_tpilot_index].real(), 0);
+ }
+ }
+
+ return d_tps_carriers_val[d_tpilot_index];
+ }
+
+ void
+ dvbt_pilot_gen::advance_tpilot()
+ {
+ ++d_tpilot_index;
+ d_tpilot_index = d_tpilot_index % d_tps_carriers_size;
+ }
+
+ /*
+ * Set a number of bits to a specified value
+ */
+ void
+ dvbt_pilot_gen::set_tps_bits(int start, int stop, unsigned int data)
+ {
+ for (int i = start; i >= stop; i--) {
+ d_tps_data[i] = data & 0x1;
+ data = data >> 1;
+ }
+ }
+
+ /*
+ * Clause 4.6
+ * Format data that will be sent with TPS signals
+ * en 300 744 - section 4.6.2
+ * s0 Initialization
+ * s1-s16 Synchronization word
+ * s17-s22 Length Indicator
+ * s23-s24 Frame Number
+ * S25-s26 Constellation
+ * s27, s28, s29 Hierarchy information
+ * s30, s31, s32 Code rate, HP stream
+ * s33, s34, s35 Code rate, LP stream
+ * s36, s37 Guard interval
+ * s38, s39 Transmission mode
+ * s40, s47 Cell identifier
+ * s48-s53 All set to "0"
+ * s54-s67 Error protection (BCH code)
+ */
+ void
+ dvbt_pilot_gen::format_tps_data()
+ {
+ //Clause 4.6.3
+ set_tps_bits(0, 0, d_wk[0]);
+ //Clause 4.6.2.2
+ if (d_frame_index % 2) {
+ set_tps_bits(16, 1, 0xca11);
+ }
+ else {
+ set_tps_bits(16, 1, 0x35ee);
+ }
+ //Clause 4.6.2.3
+ if (config.d_include_cell_id) {
+ set_tps_bits(22, 17, 0x1f);
+ }
+ else {
+ set_tps_bits(22, 17, 0x17);
+ }
+ //Clause 4.6.2.4
+ set_tps_bits(24, 23, d_frame_index);
+ //Clause 4.6.2.5
+ set_tps_bits(26, 25, config.d_constellation);
+ //Clause 4.6.2.6
+ set_tps_bits(29, 27, config.d_hierarchy);
+ //Clause 4.6.2.7
+ switch (config.d_code_rate_HP) {
+ case C1_2:
+ set_tps_bits(32, 30, 0);
+ break;
+ case C2_3:
+ set_tps_bits(32, 30, 1);
+ break;
+ case C3_4:
+ set_tps_bits(32, 30, 2);
+ break;
+ case C5_6:
+ set_tps_bits(32, 30, 3);
+ break;
+ case C7_8:
+ set_tps_bits(32, 30, 4);
+ break;
+ default:
+ set_tps_bits(32, 30, 0);
+ break;
+ }
+ switch (config.d_code_rate_LP) {
+ case C1_2:
+ set_tps_bits(35, 33, 0);
+ break;
+ case C2_3:
+ set_tps_bits(35, 33, 1);
+ break;
+ case C3_4:
+ set_tps_bits(35, 33, 2);
+ break;
+ case C5_6:
+ set_tps_bits(35, 33, 3);
+ break;
+ case C7_8:
+ set_tps_bits(35, 33, 4);
+ break;
+ default:
+ set_tps_bits(35, 33, 0);
+ break;
+ }
+ //Clause 4.6.2.8
+ set_tps_bits(37, 36, config.d_guard_interval);
+ //Clause 4.6.2.9
+ set_tps_bits(39, 38, config.d_transmission_mode);
+ //Clause 4.6.2.10
+ set_tps_bits(47, 40, config.d_cell_id);
+ //These bits are set to zero
+ set_tps_bits(53, 48, 0);
+ //Clause 4.6.2.11
+ generate_bch_code();
+ }
+
+ int
+ dvbt_pilot_gen::process_tps_data(const gr_complex * in, const int diff_symbol_index)
+ {
+ int end_frame = 0;
+
+ // Look for TPS data only - demodulate DBPSK
+ // Calculate phase difference between previous symbol
+ // and current one to determine the current bit.
+ // Use majority voting for decision
+ int tps_majority_zero = 0;
+
+ for (int k = 0; k < d_tps_carriers_size; k++) {
+ // Use equalizer to correct data and frequency correction
+ gr_complex val = in[d_zeros_on_left + d_tps_carriers[k]] * d_channel_gain[d_tps_carriers[k]];
+
+ if (!d_symbol_index_known || (d_symbol_index != 0)) {
+ gr_complex phdiff = val * conj(d_prev_tps_symbol[k]);
+
+ if (phdiff.real() >= 0.0) {
+ tps_majority_zero++;
+ }
+ else {
+ tps_majority_zero--;
+ }
+ }
+
+ d_prev_tps_symbol[k] = val;
+ }
+
+ // Insert obtained TPS bit into FIFO
+ // Insert the same bit into FIFO in the case
+ // diff_symbol_index is more than one. This will happen
+ // in the case of losing 1 to 3 symbols.
+ // This could be corrected by BCH decoder afterwards.
+
+ for (int i = 0; i < diff_symbol_index; i++) {
+ // Take out the front entry first
+ d_rcv_tps_data.pop_front();
+
+ // Add data at tail
+ if (!d_symbol_index_known || (d_symbol_index != 0)) {
+ if (tps_majority_zero >= 0) {
+ d_rcv_tps_data.push_back(0);
+ }
+ else {
+ d_rcv_tps_data.push_back(1);
+ }
+ }
+ else {
+ d_rcv_tps_data.push_back(0);
+ }
+ }
+
+ // Match synchronization signatures
+ if (std::equal(d_rcv_tps_data.begin() + 1, d_rcv_tps_data.begin() + d_tps_sync_evenv.size(), d_tps_sync_evenv.begin())) {
+ // Verify parity for TPS data
+ if (!verify_bch_code(d_rcv_tps_data)) {
+ d_frame_index = (d_rcv_tps_data[23] << 1) | (d_rcv_tps_data[24]);
+
+ d_symbol_index_known = 1;
+ end_frame = 1;
+ }
+ else {
+ d_symbol_index_known = 0;
+ end_frame = 0;
+ }
+
+ // Clear up FIFO
+ for (int i = 0; i < d_symbols_per_frame; i++) {
+ d_rcv_tps_data[i] = 0;
+ }
+ }
+ else if (std::equal(d_rcv_tps_data.begin() + 1, d_rcv_tps_data.begin() + d_tps_sync_oddv.size(), d_tps_sync_oddv.begin())) {
+ // Verify parity for TPS data
+ if (!verify_bch_code(d_rcv_tps_data)) {
+ d_frame_index = (d_rcv_tps_data[23] << 1) | (d_rcv_tps_data[24]);
+
+ d_symbol_index_known = 1;
+ end_frame = 1;
+ }
+ else {
+ d_symbol_index_known = 0;
+ end_frame = 0;
+ }
+
+ // Clear up FIFO
+ for (int i = 0; i < d_symbols_per_frame; i++) {
+ d_rcv_tps_data[i] = 0;
+ }
+ }
+
+ return end_frame;
+ }
+
+ void
+ dvbt_pilot_gen::set_chanestim_carrier(int k)
+ {
+ d_chanestim_carriers[d_chanestim_index] = k;
+ }
+
+ void
+ dvbt_pilot_gen::advance_chanestim()
+ {
+ d_chanestim_index++;
+ }
+
+ int
+ dvbt_pilot_gen::get_current_payload()
+ {
+ return d_payload_carriers[d_payload_index];
+ }
+
+ void
+ dvbt_pilot_gen::set_payload_carrier(int k)
+ {
+ d_payload_carriers[d_payload_index] = k;
+ }
+
+ void
+ dvbt_pilot_gen::advance_payload()
+ {
+ d_payload_index++;
+ }
+
+ void
+ dvbt_pilot_gen::process_payload_data(const gr_complex *in, gr_complex *out)
+ {
+ //reset indexes
+ d_spilot_index = 0; d_cpilot_index = 0; d_tpilot_index = 0;
+ d_payload_index = 0;d_chanestim_index = 0;
+ int is_payload = 1;
+
+ //process one block - one symbol
+ for (int k = 0; k < (d_Kmax - d_Kmin + 1); k++) {
+ is_payload = 1;
+
+ // Keep data for channel estimation
+ // This depends on the symbol index
+ if (k == get_current_spilot(d_mod_symbol_index)) {
+ advance_spilot(d_mod_symbol_index);
+ is_payload = 0;
+ }
+
+ // Keep data for frequency correction
+ // and channel estimation
+ if (k == get_current_cpilot()) {
+ advance_cpilot();
+ is_payload = 0;
+ }
+
+ if (k == get_current_tpilot()) {
+ advance_tpilot();
+ is_payload = 0;
+ }
+
+ // Keep payload carrier number
+ // This depends on the symbol index
+ if (is_payload) {
+ set_payload_carrier(k);
+ advance_payload();
+ }
+ }
+
+ if (d_equalizer_ready) {
+ // Equalize payload data according to channel estimator
+ for (int i = 0; i < d_payload_index; i++) {
+ out[i] = in[d_zeros_on_left + d_payload_carriers[i]] * d_channel_gain[d_payload_carriers[i]];
+ }
+ }
+ else {
+ // If equ not ready, return 0
+ for (int i = 0; i < d_payload_length; i++) {
+ out[0] = gr_complex(0.0, 0.0);
+ }
+ }
+ }
+
+ void
+ dvbt_pilot_gen::update_output(const gr_complex *in, gr_complex *out)
+ {
+ int is_payload = 1;
+ int payload_count = 0;
+
+ //move to the next symbol
+ //re-genereate TPS data
+ format_tps_data();
+
+ //reset indexes
+ payload_count = 0;
+ d_spilot_index = 0; d_cpilot_index = 0; d_tpilot_index = 0;
+
+ for (int i = 0; i < d_zeros_on_left; i++) {
+ out[i] = gr_complex(0.0, 0.0);
+ }
+
+ //process one block - one symbol
+ for (int k = d_Kmin; k < (d_Kmax - d_Kmin + 1); k++) {
+ is_payload = 1;
+ if (k == get_current_spilot(d_symbol_index)) {
+ out[d_zeros_on_left + k] = get_spilot_value(k);
+ advance_spilot(d_symbol_index);
+ is_payload = 0;
+ }
+
+ if (k == get_current_cpilot()) {
+ out[d_zeros_on_left + k] = get_cpilot_value(k);
+ advance_cpilot();
+ is_payload = 0;
+ }
+
+ if (k == get_current_tpilot()) {
+ out[d_zeros_on_left + k] = get_tpilot_value(k);
+ advance_tpilot();
+ is_payload = 0;
+ }
+
+ if (is_payload == 1) {
+ out[d_zeros_on_left + k] = in[payload_count++];
+ }
+ }
+
+ // update indexes
+ if (++d_symbol_index == d_symbols_per_frame) {
+ d_symbol_index = 0;
+ if (++d_frame_index == d_frames_per_superframe) {
+ d_frame_index = 0;
+ d_superframe_index++;
+ }
+ }
+
+ for (int i = (d_fft_length - d_zeros_on_right); i < d_fft_length; i++) {
+ out[i] = gr_complex(0.0, 0.0);
+ }
+ }
+
+ int
+ dvbt_pilot_gen::parse_input(const gr_complex *in, gr_complex *out, int * symbol_index, int * frame_index)
+ {
+ d_trigger_index++;
+
+ // Obtain frequency correction based on cpilots.
+ // Obtain channel estimation based on both
+ // cpilots and spilots.
+ // We use spilot correlation for finding the symbol index modulo 4
+ // The diff between previous sym index and current index is used
+ // to advance the symbol index inside a frame (0 to 67)
+ // Then based on the TPS data we find out the start of a frame
+
+ // Process cpilot data
+ // This is post FFT integer frequency offset estimation
+ // This is called before all other processing
+ process_cpilot_data(in);
+
+ // Compute one shot Post-FFT Carrier and Sampling Frequency Tracking
+ // Obtain fractional Carrer and Sampling frequency corrections
+ // Before this moment it is assumed to have corrected this:
+ // - symbol timing (pre-FFT)
+ // - symbol frequency correction (pre-FFT)
+ // - integer frequency correction (post-FFT)
+ // TODO - call this just in the aquisition mode
+ compute_oneshot_csft(in);
+
+ // Gather all corrections and obtain a corrected OFDM symbol:
+ // - input symbol shift (post-FFT)
+ // - integer frequency correction (post-FFT)
+ // - fractional frequency (carrier and sampling) corrections (post-FFT)
+ // TODO - use PI to update the corrections
+ frequency_correction(in, d_derot_in);
+
+ // Process spilot data
+ // This is channel estimation function
+ int diff_symbol_index = process_spilot_data(d_derot_in);
+
+ // Correct symbol index so that all subsequent processing
+ // use correct symbol index
+ d_symbol_index = (d_symbol_index + diff_symbol_index) % d_symbols_per_frame;
+
+ // Symbol index is used in other modules too
+ *symbol_index = d_symbol_index;
+ // Frame index is used in other modules too
+ *frame_index = d_frame_index;
+
+ // Process TPS data
+ // If a frame is recognized then signal end of frame
+ int frame_end = process_tps_data(d_derot_in, diff_symbol_index);
+
+ // We are just at the end of a frame
+ if (frame_end) {
+ d_symbol_index = d_symbols_per_frame - 1;
+ }
+
+ // Process payload data with correct symbol index
+ process_payload_data(d_derot_in, out);
+
+ // noutput_items should be 1 in this case
+ return 1;
+ }
+
+ dvbt_reference_signals::sptr
+ dvbt_reference_signals::make(int itemsize, int ninput, int noutput, \
+ dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \
+ dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, \
+ dvb_guardinterval_t guard_interval, dvbt_transmission_mode_t transmission_mode, \
+ int include_cell_id, int cell_id)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_reference_signals_impl(itemsize, ninput, \
+ noutput, constellation, hierarchy, code_rate_HP, code_rate_LP, \
+ guard_interval, transmission_mode, include_cell_id, cell_id));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_reference_signals_impl::dvbt_reference_signals_impl(int itemsize, int ninput, int noutput, \
+ dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, dvb_code_rate_t code_rate_HP,\
+ dvb_code_rate_t code_rate_LP, dvb_guardinterval_t guard_interval,\
+ dvbt_transmission_mode_t transmission_mode, int include_cell_id, int cell_id)
+ : block("dvbt_reference_signals",
+ io_signature::make(1, 1, itemsize * ninput),
+ io_signature::make(1, 1, itemsize * noutput)),
+ config(constellation, hierarchy, code_rate_HP, code_rate_LP, \
+ guard_interval, transmission_mode, include_cell_id, cell_id),
+ d_pg(config)
+ {
+ d_ninput = ninput;
+ d_noutput = noutput;
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_reference_signals_impl::~dvbt_reference_signals_impl()
+ {
+ }
+
+ void
+ dvbt_reference_signals_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ }
+
+ int
+ dvbt_reference_signals_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const gr_complex *in = (const gr_complex *) input_items[0];
+ gr_complex *out = (gr_complex *) output_items[0];
+
+ for (int i = 0; i < noutput_items; i++) {
+ d_pg.update_output(&in[i * d_ninput], &out[i * d_noutput]);
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (noutput_items);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
+
diff --git a/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h
new file mode 100644
index 0000000000..7d356203cb
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_reference_signals_impl.h
@@ -0,0 +1,258 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_IMPL_H
+#define INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_IMPL_H
+
+#include <gnuradio/dtv/dvbt_reference_signals.h>
+#include "dvbt_configure.h"
+#include <vector>
+#include <deque>
+
+ // This should eventually go into a const file
+ const int SYMBOLS_PER_FRAME = 68;
+ const int FRAMES_PER_SUPERFRAME = 4;
+
+ const int SCATTERED_PILOT_SIZE_2k = 142;
+ const int CONTINUAL_PILOT_SIZE_2k = 45;
+ const int TPS_PILOT_SIZE_2k = 17;
+
+ const int SCATTERED_PILOT_SIZE_8k = 568;
+ const int CONTINUAL_PILOT_SIZE_8k = 177;
+ const int TPS_PILOT_SIZE_8k = 68;
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_pilot_gen {
+ private:
+ // this should be first in order to be initialized first
+ const dvbt_configure &config;
+
+ int d_Kmin;
+ int d_Kmax;
+ int d_fft_length;
+ int d_payload_length;
+ int d_zeros_on_left;
+ int d_zeros_on_right;
+ int d_cp_length;
+
+ static const int d_symbols_per_frame;
+ static const int d_frames_per_superframe;
+
+ // 2k mode
+ // scattered pilot carriers info
+ static const int d_spilot_carriers_size_2k;
+
+ // continual pilot carriers info
+ static const int d_cpilot_carriers_size_2k;
+ static const int d_cpilot_carriers_2k[];
+
+ // TPS carriers info
+ static const int d_tps_carriers_size_2k;
+ static const int d_tps_carriers_2k[];
+
+ //8k mode
+ // scattered pilot carriers info
+ static const int d_spilot_carriers_size_8k;
+
+ // continual pilot carriers info
+ static const int d_cpilot_carriers_size_8k;
+ static const int d_cpilot_carriers_8k[];
+
+ // TPS carriers info
+ static const int d_tps_carriers_size_8k;
+ static const int d_tps_carriers_8k[];
+
+ // TPS sync data
+ static const int d_tps_sync_size;
+ static const int d_tps_sync_even[];
+ static const int d_tps_sync_odd[];
+
+ // Variables to keep data for 2k, 8k, 4k
+ int d_spilot_carriers_size;
+ gr_complex * d_spilot_carriers_val;
+ gr_complex * d_channel_gain;
+
+ int d_cpilot_carriers_size;
+ const int * d_cpilot_carriers;
+ float * d_known_phase_diff;
+ float * d_cpilot_phase_diff;
+ int d_freq_offset;
+ float d_carrier_freq_correction;
+ float d_sampling_freq_correction;
+
+ // Variable to keep corrected OFDM symbol
+ gr_complex * d_derot_in;
+
+ int d_tps_carriers_size;
+ const int * d_tps_carriers;
+ gr_complex * d_tps_carriers_val;
+
+ // Keeps TPS data
+ unsigned char * d_tps_data;
+ // Keep TPS carriers values from previous symbol
+ gr_complex * d_prev_tps_symbol;
+ // Keep TPS carriers values from current symbol
+ gr_complex * d_tps_symbol;
+ // Keeps the rcv TPS data, is a FIFO
+ std::deque<char> d_rcv_tps_data;
+ // Keeps the TPS sync sequence
+ std::deque<char> d_tps_sync_evenv;
+ std::deque<char> d_tps_sync_oddv;
+
+ // Keeps channel estimation carriers
+ // we use both continual and scattered carriers
+ int * d_chanestim_carriers;
+
+ // Keeps paload carriers
+ int * d_payload_carriers;
+
+ // Indexes for all carriers
+ int d_spilot_index;
+ int d_cpilot_index;
+ int d_tpilot_index;
+ int d_symbol_index;
+ int d_symbol_index_known;
+ int d_frame_index;
+ int d_superframe_index;
+ int d_freq_offset_max;
+ int d_trigger_index;
+ int d_payload_index;
+ int d_chanestim_index;
+ int d_prev_mod_symbol_index;
+ int d_mod_symbol_index;
+ int d_equalizer_ready;
+
+ // PRPS generator data buffer
+ char * d_wk;
+ // Generate PRBS
+ void generate_prbs();
+
+ // TPS private methods
+ void set_tps_bits(int start, int stop, unsigned int data);
+
+ void set_symbol_index(int index);
+ int get_symbol_index();
+ void set_tps_data();
+ void get_tps_data();
+
+ void reset_pilot_generator();
+
+ // Scattered pilot generator methods
+ int get_current_spilot(int spilot) const;
+ gr_complex get_spilot_value(int spilot);
+ void set_spilot_value(int spilot, gr_complex val);
+ void advance_spilot(int sindex);
+ // Methods used to quick iterate through all spilots
+ int get_first_spilot();
+ int get_last_spilot() const;
+ int get_next_spilot();
+ // Scattered pilot data processing method
+ int process_spilot_data(const gr_complex * in);
+
+ // Channel estimation methods
+ void set_channel_gain(int spilot, gr_complex val);
+
+ // Continual pilot generator methods
+ int get_current_cpilot() const;
+ gr_complex get_cpilot_value(int cpilot);
+ void advance_cpilot();
+ // Continual pilot data processing methods
+ void process_cpilot_data(const gr_complex * in);
+ void compute_oneshot_csft(const gr_complex * in);
+ gr_complex * frequency_correction(const gr_complex * in, gr_complex * out);
+
+ // TPS generator methods
+ int get_current_tpilot() const;
+ gr_complex get_tpilot_value(int tpilot);
+ void advance_tpilot();
+ // TPS data
+ void format_tps_data();
+ // Encode TPS data
+ void generate_bch_code();
+ // Verify parity on TPS data
+ int verify_bch_code(std::deque<char> data);
+ // TPS data processing metods
+ int process_tps_data(const gr_complex * in, const int diff_symbo_index);
+
+ // Channel estimation methods
+ void set_chanestim_carrier(int k);
+
+ // Payload data processing methods
+ int get_current_payload();
+ void advance_chanestim();
+ void set_payload_carrier(int k);
+ void advance_payload();
+ void process_payload_data(const gr_complex *in, gr_complex *out);
+
+ public:
+ dvbt_pilot_gen(const dvbt_configure &config);
+ ~dvbt_pilot_gen();
+
+ /*!
+ * ETSI EN 300 744 Clause 4.5. \n
+ * Update a set of carriers with the pilot signals. \n
+ */
+ void update_output(const gr_complex *in, gr_complex *out);
+
+ /*!
+ * TODO
+ * ETSI EN 300 744 Clause 4.5. \n
+ * Extract data from a set of carriers using pilot signals. \n
+ * This is doing frequency correcton, equalization. \n
+ */
+ int parse_input(const gr_complex *in, gr_complex *out, int * symbol_index, int * frame_index);
+ };
+
+ class dvbt_reference_signals_impl : public dvbt_reference_signals
+ {
+ // configuration object for this class
+ const dvbt_configure config;
+
+ private:
+ // Pilot Generator object
+ dvbt_pilot_gen d_pg;
+
+ //In and Out data length
+ int d_ninput;
+ int d_noutput;
+
+ public:
+ dvbt_reference_signals_impl(int itemsize, int ninput, int noutput, \
+ dvb_constellation_t constellation, dvbt_hierarchy_t hierarchy, \
+ dvb_code_rate_t code_rate_HP, dvb_code_rate_t code_rate_LP, \
+ dvb_guardinterval_t guard_interval, \
+ dvbt_transmission_mode_t transmission_mode = gr::dtv::T2k, int include_cell_id = 0, int cell_id = 0);
+ ~dvbt_reference_signals_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_REFERENCE_SIGNALS_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc
new file mode 100644
index 0000000000..64d242d5fb
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.cc
@@ -0,0 +1,222 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "dvbt_symbol_inner_interleaver_impl.h"
+#include <stdio.h>
+
+namespace gr {
+ namespace dtv {
+
+ const char dvbt_symbol_inner_interleaver_impl::d_bit_perm_2k[] = {4, 3, 9, 6, 2, 8, 1, 5, 7, 0};
+ const char dvbt_symbol_inner_interleaver_impl::d_bit_perm_8k[] = {7, 1, 4, 2, 9, 6, 8, 10, 0, 3, 11, 5};
+
+ void
+ dvbt_symbol_inner_interleaver_impl::generate_H()
+ {
+ const int Mmax = d_fft_length;
+ const int Nmax = d_payload_length;
+ const int Nr = int(ceil(log2(d_fft_length)));
+ int q = 0;
+
+ for (int i = 0; i < Mmax; i++) {
+ d_h[q] = ((i % 2) << (Nr - 1)) + calculate_R(i);
+ if (d_h[q] < Nmax) {
+ q++;
+ }
+ }
+ }
+
+ int
+ dvbt_symbol_inner_interleaver_impl::H(int q)
+ {
+ return d_h[q];
+ }
+
+ int
+ dvbt_symbol_inner_interleaver_impl::calculate_R(int i)
+ {
+ const int Nr = int(ceil(log2(d_fft_length)));
+ int reg = 0;
+
+ if (i == 0) {
+ reg = 0;
+ }
+ else if (i == 1) {
+ reg = 0;
+ }
+ else {
+ reg = 1;
+ for (int k = 3; k <= i; k++) {
+ char new_bit = 0;
+
+ if (d_transmission_mode == T2k) {
+ new_bit = (reg ^ (reg >> 3)) & 1;
+ }
+ else if (d_transmission_mode == T8k) {
+ new_bit = (reg ^ (reg >> 1) ^ (reg >> 4) ^ (reg >> 6)) & 1;
+ }
+ else {
+ new_bit = (reg ^ (reg >> 3)) & 1;
+ }
+
+ int mask = (1 << Nr) - 1;
+ reg = ((reg >> 1) | (new_bit << (Nr - 2))) & mask;
+ }
+ }
+
+ int newreg = 0;
+
+ for (int k = 0; k < (Nr - 1); k++) {
+ char bit = (reg >> k) & 1;
+ newreg = newreg | (bit << d_bit_perm[k]);
+ }
+
+ return newreg;
+ }
+
+ dvbt_symbol_inner_interleaver::sptr
+ dvbt_symbol_inner_interleaver::make(int nsize, dvbt_transmission_mode_t transmission, int direction)
+ {
+ return gnuradio::get_initial_sptr
+ (new dvbt_symbol_inner_interleaver_impl(nsize, transmission, direction));
+ }
+
+ /*
+ * The private constructor
+ */
+ dvbt_symbol_inner_interleaver_impl::dvbt_symbol_inner_interleaver_impl(int nsize, dvbt_transmission_mode_t transmission, int direction)
+ : block("dvbt_symbol_inner_interleaver",
+ io_signature::make(1, 1, sizeof(unsigned char) * nsize),
+ io_signature::make(1, 1, sizeof(unsigned char) * nsize)),
+ config(gr::dtv::MOD_16QAM, gr::dtv::NH, gr::dtv::C1_2, gr::dtv::C1_2, gr::dtv::GI_1_32, transmission),
+ d_nsize(nsize), d_direction(direction),
+ d_fft_length(0), d_payload_length(0),
+ d_symbol_index(0)
+ {
+ d_symbols_per_frame = config.d_symbols_per_frame;
+ d_transmission_mode = config.d_transmission_mode;
+ d_fft_length = config.d_fft_length;
+ d_payload_length = config.d_payload_length;
+ d_direction = direction;
+
+ // Verify if transmission mode matches with size of block
+ assert(d_payload_length == d_nsize);
+
+ // Allocate memory for h vector
+ d_h = new int[d_fft_length];
+ if (d_h == NULL) {
+ std::cout << "Cannot allocate memory for d_h" << std::endl;
+ exit(1);
+ }
+
+ // Setup bit permutation vectors
+ if (d_transmission_mode == T2k) {
+ d_bit_perm = d_bit_perm_2k;
+ }
+ else if (d_transmission_mode == T8k) {
+ d_bit_perm = d_bit_perm_8k;
+ }
+ else {
+ d_bit_perm = d_bit_perm_2k;
+ }
+
+ // Generate the h function
+ generate_H();
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ dvbt_symbol_inner_interleaver_impl::~dvbt_symbol_inner_interleaver_impl()
+ {
+ delete [] d_h;
+ }
+
+ void
+ dvbt_symbol_inner_interleaver_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items;
+ }
+
+ int
+ dvbt_symbol_inner_interleaver_impl::general_work (int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ const unsigned char *in = (unsigned char *) input_items[0];
+ unsigned char *out = (unsigned char *) output_items[0];
+
+ // Demod reference signals sends a tag per OFDM frame
+ // containing the symbol index.
+ std::vector<tag_t> tags;
+ const uint64_t nread = this->nitems_read(0); //number of items read on port 0
+
+ // Read all tags on the input buffer
+ this->get_tags_in_range(tags, 0, nread, nread + noutput_items, pmt::string_to_symbol("symbol_index"));
+
+ for (int k = 0; k < noutput_items; k++) {
+ int blocks = k * d_nsize;
+
+ if (d_direction) {
+ // Interleave
+ for (int q = 0; q < d_nsize; q++) {
+ if (d_symbol_index % 2) {
+ out[blocks + q] = in[blocks + H(q)];
+ }
+ else {
+ out[blocks + H(q)] = in[blocks + q];
+ }
+ }
+
+ ++d_symbol_index;
+ d_symbol_index = d_symbol_index % d_symbols_per_frame;
+ }
+ else {
+ // Deinterleave
+ d_symbol_index = pmt::to_long(tags[k].value);
+
+ for (int q = 0; q < d_nsize; q++) {
+ if (d_symbol_index % 2) {
+ out[blocks + H(q)] = in[blocks + q];
+ }
+ else {
+ out[blocks + q] = in[blocks + H(q)];
+ }
+ }
+ }
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (noutput_items);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.h b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.h
new file mode 100644
index 0000000000..6a7265d7e1
--- /dev/null
+++ b/gr-dtv/lib/dvbt/dvbt_symbol_inner_interleaver_impl.h
@@ -0,0 +1,70 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_DTV_DVBT_SYMBOL_INNER_INTERLEAVER_IMPL_H
+#define INCLUDED_DTV_DVBT_SYMBOL_INNER_INTERLEAVER_IMPL_H
+
+#include <gnuradio/dtv/dvbt_symbol_inner_interleaver.h>
+#include "dvbt_configure.h"
+
+namespace gr {
+ namespace dtv {
+
+ class dvbt_symbol_inner_interleaver_impl : public dvbt_symbol_inner_interleaver
+ {
+ private:
+ const dvbt_configure config;
+
+ int d_symbols_per_frame;
+ dvbt_transmission_mode_t d_transmission_mode;
+ int d_nsize;
+ int d_direction;
+ int d_fft_length;
+ int d_payload_length;
+
+ int * d_h;
+ const char * d_bit_perm;
+ static const char d_bit_perm_2k[];
+ static const char d_bit_perm_8k[];
+
+ //Keeps the symbol index
+ unsigned int d_symbol_index;
+
+ void generate_H();
+ int H(int q);
+ int calculate_R(int i);
+
+ public:
+ dvbt_symbol_inner_interleaver_impl(int nsize, dvbt_transmission_mode_t transmission, int direction);
+ ~dvbt_symbol_inner_interleaver_impl();
+
+ void forecast (int noutput_items, gr_vector_int &ninput_items_required);
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_DVBT_SYMBOL_INNER_INTERLEAVER_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.cc
index a09af908c9..0c05285eda 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.cc
+++ b/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.cc
@@ -30,7 +30,7 @@ namespace gr {
namespace dtv {
dvbt2_framemapper_cc::sptr
- dvbt2_framemapper_cc::make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband)
+ dvbt2_framemapper_cc::make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband)
{
return gnuradio::get_initial_sptr
(new dvbt2_framemapper_cc_impl(framesize, rate, constellation, rotation, fecblocks, tiblocks, carriermode, fftsize, guardinterval, l1constellation, pilotpattern, t2frames, numdatasyms, paprmode, version, preamble, inputmode, reservedbiasbits, l1scrambled, inband));
@@ -39,7 +39,7 @@ namespace gr {
/*
* The private constructor
*/
- dvbt2_framemapper_cc_impl::dvbt2_framemapper_cc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband)
+ dvbt2_framemapper_cc_impl::dvbt2_framemapper_cc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband)
: gr::block("dvbt2_framemapper_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(gr_complex)))
@@ -86,9 +86,6 @@ namespace gr {
break;
}
}
- fef_present = FALSE; /* for testing only */
- fef_length = 134144; /* " " " */
- fef_interval = 1; /* " " " */
l1preinit->type = STREAMTYPE_TS;
l1preinit->bwt_ext = carriermode;
fft_size = fftsize;
@@ -100,12 +97,7 @@ namespace gr {
l1preinit->l1_mod = l1constellation;
l1preinit->l1_cod = 0;
l1preinit->l1_fec_type = 0;
- if (fef_present == FALSE) {
- l1preinit->l1_post_info_size = KSIG_POST - 32;
- }
- else {
- l1preinit->l1_post_info_size = KSIG_POST + 34 - 32;
- }
+ l1preinit->l1_post_info_size = KSIG_POST - 32;
l1preinit->pilot_pattern = pilotpattern;
l1preinit->tx_id_availability = 0;
l1preinit->cell_id = 0;
@@ -144,12 +136,7 @@ namespace gr {
l1postinit->ff_flag = 0;
l1postinit->first_rf_idx = 0;
l1postinit->first_frame_idx = 0;
- if (fef_present == FALSE) {
- l1postinit->plp_group_id = 1;
- }
- else {
- l1postinit->plp_group_id = 0;
- }
+ l1postinit->plp_group_id = 1;
switch (rate) {
case C1_3:
l1postinit->plp_cod = 6;
@@ -205,14 +192,8 @@ namespace gr {
else {
l1postinit->plp_mode = inputmode + 1;
}
- if (fef_present == FALSE) {
- l1postinit->static_flag = 0;
- l1postinit->static_padding_flag = 0;
- }
- else {
- l1postinit->static_flag = 1;
- l1postinit->static_padding_flag = 1;
- }
+ l1postinit->static_flag = 0;
+ l1postinit->static_padding_flag = 0;
l1postinit->fef_length_msb = 0;
if (reservedbiasbits == RESERVED_ON && version == VERSION_131) {
l1postinit->reserved_2 = 0x3fffffff;
@@ -351,6 +332,11 @@ namespace gr {
eta_mod = 6;
break;
}
+ N_P2 = 0;
+ C_P2 = 0;
+ N_FC = 0;
+ C_FC = 0;
+ C_DATA = 0;
if ((preamble == PREAMBLE_T2_SISO) || (preamble == PREAMBLE_T2_LITE_SISO)) {
switch (fft_size) {
case FFTSIZE_1K:
@@ -904,14 +890,8 @@ namespace gr {
C_FC = 0;
}
}
- if (fef_present == FALSE) {
- N_punc_temp = (6 * (KBCH_1_2 - KSIG_POST)) / 5;
- N_post_temp = KSIG_POST + NBCH_PARITY + 9000 - N_punc_temp;
- }
- else {
- N_punc_temp = (6 * (KBCH_1_2 - (KSIG_POST + 34))) / 5;
- N_post_temp = (KSIG_POST + 34) + NBCH_PARITY + 9000 - N_punc_temp;
- }
+ N_punc_temp = (6 * (KBCH_1_2 - KSIG_POST)) / 5;
+ N_post_temp = KSIG_POST + NBCH_PARITY + 9000 - N_punc_temp;
if (N_P2 == 1) {
N_post = ceil((float)N_post_temp / (2 * (float)eta_mod)) * 2 * eta_mod;
}
@@ -1166,12 +1146,7 @@ namespace gr {
for (int n = 2; n >= 0; n--) {
l1pre[offset_bits++] = temp & (1 << n) ? 1 : 0;
}
- if (fef_present == FALSE) {
- l1pre[offset_bits++] = 0;
- }
- else {
- l1pre[offset_bits++] = 1;
- }
+ l1pre[offset_bits++] = 0;
l1pre[offset_bits++] = l1preinit->l1_repetition_flag;
temp = l1preinit->guard_interval;
for (int n = 2; n >= 0; n--) {
@@ -1356,20 +1331,6 @@ namespace gr {
for (int n = 31; n >= 0; n--) {
l1post[offset_bits++] = temp & (1 << n) ? 1 : 0;
}
- if (fef_present == TRUE) {
- temp = 0;
- for (int n = 3; n >= 0; n--) {
- l1post[offset_bits++] = temp & (1 << n) ? 1 : 0;
- }
- temp = fef_length;
- for (int n = 21; n >= 0; n--) {
- l1post[offset_bits++] = temp & (1 << n) ? 1 : 0;
- }
- temp = fef_interval;
- for (int n = 7; n >= 0; n--) {
- l1post[offset_bits++] = temp & (1 << n) ? 1 : 0;
- }
- }
temp = l1postinit->plp_id;
for (int n = 7; n >= 0; n--) {
l1post[offset_bits++] = temp & (1 << n) ? 1 : 0;
diff --git a/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.h
index 2b25b2ddd1..8d35493f45 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.h
+++ b/gr-dtv/lib/dvbt2/dvbt2_framemapper_cc_impl.h
@@ -139,9 +139,6 @@ namespace gr {
int t2_frames;
int t2_frame_num;
int l1_scrambled;
- int fef_present;
- int fef_length;
- int fef_interval;
int N_P2;
int C_P2;
int N_FC;
@@ -193,7 +190,7 @@ namespace gr {
const static int mux64[12];
public:
- dvbt2_framemapper_cc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband);
+ dvbt2_framemapper_cc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbt2_rotation_t rotation, int fecblocks, int tiblocks, dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, dvbt2_l1constellation_t l1constellation, dvbt2_pilotpattern_t pilotpattern, int t2frames, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_inputmode_t inputmode, dvbt2_reservedbiasbits_t reservedbiasbits, dvbt2_l1scrambled_t l1scrambled, dvbt2_inband_t inband);
~dvbt2_framemapper_cc_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
diff --git a/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.cc
index acee74321b..f89d2af7f7 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.cc
+++ b/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.cc
@@ -29,7 +29,7 @@ namespace gr {
namespace dtv {
dvbt2_freqinterleaver_cc::sptr
- dvbt2_freqinterleaver_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble)
+ dvbt2_freqinterleaver_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble)
{
return gnuradio::get_initial_sptr
(new dvbt2_freqinterleaver_cc_impl(carriermode, fftsize, pilotpattern, guardinterval, numdatasyms, paprmode, version, preamble));
@@ -38,7 +38,7 @@ namespace gr {
/*
* The private constructor
*/
- dvbt2_freqinterleaver_cc_impl::dvbt2_freqinterleaver_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble)
+ dvbt2_freqinterleaver_cc_impl::dvbt2_freqinterleaver_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble)
: gr::sync_block("dvbt2_freqinterleaver_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(gr_complex)))
diff --git a/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.h
index 18ce8895b9..a52dc9ed94 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.h
+++ b/gr-dtv/lib/dvbt2/dvbt2_freqinterleaver_cc_impl.h
@@ -57,7 +57,7 @@ namespace gr {
const static int bitperm32k[14];
public:
- dvbt2_freqinterleaver_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble);
+ dvbt2_freqinterleaver_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble);
~dvbt2_freqinterleaver_cc_impl();
int work(int noutput_items,
diff --git a/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.cc
index 3f19c31c48..a3d2684650 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.cc
+++ b/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.cc
@@ -29,7 +29,7 @@ namespace gr {
namespace dtv {
dvbt2_miso_cc::sptr
- dvbt2_miso_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode)
+ dvbt2_miso_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode)
{
return gnuradio::get_initial_sptr
(new dvbt2_miso_cc_impl(carriermode, fftsize, pilotpattern, guardinterval, numdatasyms, paprmode));
@@ -38,7 +38,7 @@ namespace gr {
/*
* The private constructor
*/
- dvbt2_miso_cc_impl::dvbt2_miso_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode)
+ dvbt2_miso_cc_impl::dvbt2_miso_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode)
: gr::sync_block("dvbt2_miso_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(2, 2, sizeof(gr_complex)))
diff --git a/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.h
index e33b201d21..8dcbdf9c7a 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.h
+++ b/gr-dtv/lib/dvbt2/dvbt2_miso_cc_impl.h
@@ -38,7 +38,7 @@ namespace gr {
int C_DATA;
public:
- dvbt2_miso_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode);
+ dvbt2_miso_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode);
~dvbt2_miso_cc_impl();
int work(int noutput_items,
diff --git a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc
index 22415af97b..9a2a41b395 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc
+++ b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.cc
@@ -30,7 +30,7 @@ namespace gr {
namespace dtv {
dvbt2_p1insertion_cc::sptr
- dvbt2_p1insertion_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip)
+ dvbt2_p1insertion_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip)
{
return gnuradio::get_initial_sptr
(new dvbt2_p1insertion_cc_impl(carriermode, fftsize, guardinterval, numdatasyms, preamble, showlevels, vclip));
@@ -39,13 +39,12 @@ namespace gr {
/*
* The private constructor
*/
- dvbt2_p1insertion_cc_impl::dvbt2_p1insertion_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip)
+ dvbt2_p1insertion_cc_impl::dvbt2_p1insertion_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip)
: gr::block("dvbt2_p1insertion_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(gr_complex)))
{
int s1, s2, index = 0;
- int fef_present = FALSE; /* for testing only */
const gr_complex *in = (const gr_complex *) p1_freq;
gr_complex *out = (gr_complex *) p1_time;
s1 = preamble;
@@ -103,9 +102,6 @@ namespace gr {
}
init_p1_randomizer();
s2 = (fftsize & 0x7) << 1;
- if (fef_present == TRUE) {
- s2 |= 1;
- }
for (int i = 0; i < 8; i++) {
for (int j = 7; j >= 0; j--) {
modulation_sequence[index++] = (s1_modulation_patterns[s1][i] >> j) & 0x1;
diff --git a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h
index 85537b5b34..3931723009 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h
+++ b/gr-dtv/lib/dvbt2/dvbt2_p1insertion_cc_impl.h
@@ -67,7 +67,7 @@ namespace gr {
const static unsigned char s2_modulation_patterns[16][32];
public:
- dvbt2_p1insertion_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip);
+ dvbt2_p1insertion_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_preamble_t preamble, dvbt2_showlevels_t showlevels, float vclip);
~dvbt2_p1insertion_cc_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
diff --git a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc
index db3fd00035..b4f17564af 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc
+++ b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.cc
@@ -31,7 +31,7 @@ namespace gr {
namespace dtv {
dvbt2_paprtr_cc::sptr
- dvbt2_paprtr_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength)
+ dvbt2_paprtr_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength)
{
return gnuradio::get_initial_sptr
(new dvbt2_paprtr_cc_impl(carriermode, fftsize, pilotpattern, guardinterval, numdatasyms, paprmode, version, vclip, iterations, vlength));
@@ -40,7 +40,7 @@ namespace gr {
/*
* The private constructor
*/
- dvbt2_paprtr_cc_impl::dvbt2_paprtr_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength)
+ dvbt2_paprtr_cc_impl::dvbt2_paprtr_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength)
: gr::sync_block("dvbt2_paprtr_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex) * vlength),
gr::io_signature::make(1, 1, sizeof(gr_complex) * vlength))
@@ -500,6 +500,8 @@ namespace gr {
dy = 16;
break;
}
+ shift = 0;
+ papr_map = p2_papr_map;
fft_size = fftsize;
pilot_pattern = pilotpattern;
carrier_mode = carriermode;
diff --git a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h
index 96c669f8aa..aac5e48c3f 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h
+++ b/gr-dtv/lib/dvbt2/dvbt2_paprtr_cc_impl.h
@@ -97,7 +97,7 @@ namespace gr {
const static int tr_papr_map_32k[288];
public:
- dvbt2_paprtr_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength);
+ dvbt2_paprtr_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, float vclip, int iterations, int vlength);
~dvbt2_paprtr_cc_impl();
int work(int noutput_items,
diff --git a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc
index 05dacce62d..26c83492b9 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc
+++ b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.cc
@@ -30,7 +30,7 @@ namespace gr {
namespace dtv {
dvbt2_pilotgenerator_cc::sptr
- dvbt2_pilotgenerator_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength)
+ dvbt2_pilotgenerator_cc::make(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength)
{
return gnuradio::get_initial_sptr
(new dvbt2_pilotgenerator_cc_impl(carriermode, fftsize, pilotpattern, guardinterval, numdatasyms, paprmode, version, preamble, misogroup, equalization, bandwidth, vlength));
@@ -39,7 +39,7 @@ namespace gr {
/*
* The private constructor
*/
- dvbt2_pilotgenerator_cc_impl::dvbt2_pilotgenerator_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength)
+ dvbt2_pilotgenerator_cc_impl::dvbt2_pilotgenerator_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength)
: gr::block("dvbt2_pilotgenerator_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(gr_complex) * vlength))
diff --git a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h
index e4198721f3..f99d8a603f 100644
--- a/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h
+++ b/gr-dtv/lib/dvbt2/dvbt2_pilotgenerator_cc_impl.h
@@ -155,7 +155,7 @@ namespace gr {
const static int pp8_32k[6];
public:
- dvbt2_pilotgenerator_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvbt2_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength);
+ dvbt2_pilotgenerator_cc_impl(dvbt2_extended_carrier_t carriermode, dvbt2_fftsize_t fftsize, dvbt2_pilotpattern_t pilotpattern, dvb_guardinterval_t guardinterval, int numdatasyms, dvbt2_papr_t paprmode, dvbt2_version_t version, dvbt2_preamble_t preamble, dvbt2_misogroup_t misogroup, dvbt2_equalization_t equalization, dvbt2_bandwidth_t bandwidth, int vlength);
~dvbt2_pilotgenerator_cc_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
diff --git a/gr-dtv/swig/dtv_swig.i b/gr-dtv/swig/dtv_swig.i
index 42a7b0de09..094e8f0faf 100644
--- a/gr-dtv/swig/dtv_swig.i
+++ b/gr-dtv/swig/dtv_swig.i
@@ -44,6 +44,7 @@
#include "gnuradio/dtv/atsc_trellis_encoder.h"
#include "gnuradio/dtv/atsc_viterbi_decoder.h"
#include "gnuradio/dtv/dvb_config.h"
+#include "gnuradio/dtv/dvbt_config.h"
#include "gnuradio/dtv/dvbt2_config.h"
#include "gnuradio/dtv/dvbs2_config.h"
#include "gnuradio/dtv/dvb_bbheader_bb.h"
@@ -62,6 +63,14 @@
#include "gnuradio/dtv/dvbs2_interleaver_bb.h"
#include "gnuradio/dtv/dvbs2_modulator_bc.h"
#include "gnuradio/dtv/dvbs2_physical_cc.h"
+#include "gnuradio/dtv/dvbt_energy_dispersal.h"
+#include "gnuradio/dtv/dvbt_reed_solomon_enc.h"
+#include "gnuradio/dtv/dvbt_convolutional_interleaver.h"
+#include "gnuradio/dtv/dvbt_inner_coder.h"
+#include "gnuradio/dtv/dvbt_bit_inner_interleaver.h"
+#include "gnuradio/dtv/dvbt_symbol_inner_interleaver.h"
+#include "gnuradio/dtv/dvbt_map.h"
+#include "gnuradio/dtv/dvbt_reference_signals.h"
%}
%include "gnuradio/dtv/atsc_deinterleaver.h"
@@ -80,6 +89,7 @@
%include "gnuradio/dtv/atsc_trellis_encoder.h"
%include "gnuradio/dtv/atsc_viterbi_decoder.h"
%include "gnuradio/dtv/dvb_config.h"
+%include "gnuradio/dtv/dvbt_config.h"
%include "gnuradio/dtv/dvbt2_config.h"
%include "gnuradio/dtv/dvbs2_config.h"
%include "gnuradio/dtv/dvb_bbheader_bb.h"
@@ -98,6 +108,14 @@
%include "gnuradio/dtv/dvbs2_interleaver_bb.h"
%include "gnuradio/dtv/dvbs2_modulator_bc.h"
%include "gnuradio/dtv/dvbs2_physical_cc.h"
+%include "gnuradio/dtv/dvbt_energy_dispersal.h"
+%include "gnuradio/dtv/dvbt_reed_solomon_enc.h"
+%include "gnuradio/dtv/dvbt_convolutional_interleaver.h"
+%include "gnuradio/dtv/dvbt_inner_coder.h"
+%include "gnuradio/dtv/dvbt_bit_inner_interleaver.h"
+%include "gnuradio/dtv/dvbt_symbol_inner_interleaver.h"
+%include "gnuradio/dtv/dvbt_map.h"
+%include "gnuradio/dtv/dvbt_reference_signals.h"
GR_SWIG_BLOCK_MAGIC2(dtv, atsc_deinterleaver);
GR_SWIG_BLOCK_MAGIC2(dtv, atsc_depad);
@@ -130,3 +148,11 @@ GR_SWIG_BLOCK_MAGIC2(dtv, dvbt2_miso_cc);
GR_SWIG_BLOCK_MAGIC2(dtv, dvbs2_interleaver_bb);
GR_SWIG_BLOCK_MAGIC2(dtv, dvbs2_modulator_bc);
GR_SWIG_BLOCK_MAGIC2(dtv, dvbs2_physical_cc);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_energy_dispersal);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reed_solomon_enc);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_convolutional_interleaver);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_inner_coder);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_bit_inner_interleaver);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_symbol_inner_interleaver);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_map);
+GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reference_signals);
diff --git a/gr-fcd/grc/fcd_source_c.xml b/gr-fcd/grc/fcd_source_c.xml
index b514c6126c..01ea26d81c 100644
--- a/gr-fcd/grc/fcd_source_c.xml
+++ b/gr-fcd/grc/fcd_source_c.xml
@@ -3,7 +3,7 @@
<name>Funcube Dongle Source</name>
<key>fcd_source_c</key>
<category>FCD</category>
- <throttle>1</throttle>
+ <flags>throttle</flags>
<import>from gnuradio import fcd</import>
<make>fcd.source_c($device_name)
#if $lna() != 20.0
diff --git a/gr-fec/lib/gf2mat.cc b/gr-fec/lib/gf2mat.cc
index 87cb300890..accc2859f2 100644
--- a/gr-fec/lib/gf2mat.cc
+++ b/gr-fec/lib/gf2mat.cc
@@ -109,13 +109,13 @@ GF2Vec GF2Mat::get_col(int i) {
void GF2Mat::add_cols(int i, int j) {
for ( int row = 0; row < M; row++ ) {
- H[row][i] = H[row][i] xor H[row][j];
+ H[row][i] = H[row][i] ^ H[row][j];
}
}
void GF2Mat::add_rows(int i, int j) {
for ( int col = 0; col < N; col++ ) {
- H[i][col] = H[i][col] xor H[j][col];
+ H[i][col] = H[i][col] ^ H[j][col];
}
}
diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt
index 48b59ef099..a6229f38f4 100644
--- a/gr-filter/examples/CMakeLists.txt
+++ b/gr-filter/examples/CMakeLists.txt
@@ -42,6 +42,7 @@ GR_PYTHON_INSTALL(PROGRAMS
install(
FILES
+ filter_taps.grc
resampler_demo.grc
DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR}
COMPONENT "filter_python"
diff --git a/gr-filter/examples/filter_taps.grc b/gr-filter/examples/filter_taps.grc
new file mode 100644
index 0000000000..48d37b228a
--- /dev/null
+++ b/gr-filter/examples/filter_taps.grc
@@ -0,0 +1,1299 @@
+<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.7'?>
+<flow_graph>
+ <timestamp>Wed Apr 8 11:00:48 2015</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>filter_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>qt_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sym_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>samp_rate/sps</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1080, 171)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>sps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1016, 171)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>bp_low</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>6000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(120, 139)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>cutoff_high</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>14000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 211)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>transition</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 283)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>cutoff_low</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 147)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>bp_high</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>10000</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(120, 211)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>len_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>len(lp_taps)</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(288, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_band_pass_filter_taps</key>
+ <param>
+ <key>id</key>
+ <value>bp_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>taps_real</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>low_cutoff_freq</key>
+ <value>bp_low</value>
+ </param>
+ <param>
+ <key>high_cutoff_freq</key>
+ <value>bp_high</value>
+ </param>
+ <param>
+ <key>width</key>
+ <value>transition</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ </param>
+ <param>
+ <key>beta</key>
+ <value>6.76</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(696, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_high_pass_filter_taps</key>
+ <param>
+ <key>id</key>
+ <value>hp_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>cutoff_freq</key>
+ <value>cutoff_low</value>
+ </param>
+ <param>
+ <key>width</key>
+ <value>transition</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ </param>
+ <param>
+ <key>beta</key>
+ <value>6.76</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(536, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_low_pass_filter_taps</key>
+ <param>
+ <key>id</key>
+ <value>lp_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>cutoff_freq</key>
+ <value>cutoff_high</value>
+ </param>
+ <param>
+ <key>width</key>
+ <value>transition</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ </param>
+ <param>
+ <key>beta</key>
+ <value>6.76</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(376, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_band_reject_filter_taps</key>
+ <param>
+ <key>id</key>
+ <value>br_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>low_cutoff_freq</key>
+ <value>bp_low</value>
+ </param>
+ <param>
+ <key>high_cutoff_freq</key>
+ <value>bp_high</value>
+ </param>
+ <param>
+ <key>width</key>
+ <value>transition</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ </param>
+ <param>
+ <key>beta</key>
+ <value>6.76</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(856, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fir_filter_xxx</key>
+ <param>
+ <key>id</key>
+ <value>lp_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>lp_taps</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value>Low-pass filter</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 203)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fir_filter_xxx</key>
+ <param>
+ <key>id</key>
+ <value>hp_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>hp_taps</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value>High-pass filter</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 307)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fir_filter_xxx</key>
+ <param>
+ <key>id</key>
+ <value>bp_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>bp_taps</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value>Band-pass filter</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 403)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fir_filter_xxx</key>
+ <param>
+ <key>id</key>
+ <value>br_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>br_taps</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value>Band-reject filter</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 499)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_rrc_filter_taps</key>
+ <param>
+ <key>id</key>
+ <value>rrc_taps</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gain</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>sym_rate</key>
+ <value>sym_rate</value>
+ </param>
+ <param>
+ <key>alpha</key>
+ <value>0.35</value>
+ </param>
+ <param>
+ <key>ntaps</key>
+ <value>11*sps</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1016, 35)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_fastnoise_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_fastnoise_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>noise_type</key>
+ <value>analog.GR_GAUSSIAN</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>seed</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>samples</key>
+ <value>8192</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(176, 387)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>fir_filter_xxx</key>
+ <param>
+ <key>id</key>
+ <value>rrc_filter</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fff</value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>rrc_taps</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value>RRC filter</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(392, 587)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>qtgui_freq_sink_x</key>
+ <param>
+ <key>id</key>
+ <value>qtgui_freq_sink_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>float</value>
+ </param>
+ <param>
+ <key>name</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>fftsize</key>
+ <value>4096</value>
+ </param>
+ <param>
+ <key>freqhalf</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ </param>
+ <param>
+ <key>fc</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>bw</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>grid</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>autoscale</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>0.2</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-140</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>nconnections</key>
+ <value>5</value>
+ </param>
+ <param>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
+ </param>
+ <param>
+ <key>showports</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>ctrlpanel</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>legend</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value>Low-pass</value>
+ </param>
+ <param>
+ <key>width1</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color1</key>
+ <value>"blue"</value>
+ </param>
+ <param>
+ <key>alpha1</key>
+ <value>0.9</value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value>High-pass</value>
+ </param>
+ <param>
+ <key>width2</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>alpha2</key>
+ <value>0.9</value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value>Band-pass</value>
+ </param>
+ <param>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color3</key>
+ <value>"green"</value>
+ </param>
+ <param>
+ <key>alpha3</key>
+ <value>0.9</value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value>Band-reject</value>
+ </param>
+ <param>
+ <key>width4</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"cyan"</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>0.9</value>
+ </param>
+ <param>
+ <key>label5</key>
+ <value>RRC</value>
+ </param>
+ <param>
+ <key>width5</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color5</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>alpha5</key>
+ <value>0.9</value>
+ </param>
+ <param>
+ <key>label6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width6</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color6</key>
+ <value>"magenta"</value>
+ </param>
+ <param>
+ <key>alpha6</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width7</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color7</key>
+ <value>"yellow"</value>
+ </param>
+ <param>
+ <key>alpha7</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width8</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color8</key>
+ <value>"dark red"</value>
+ </param>
+ <param>
+ <key>alpha8</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width9</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color9</key>
+ <value>"dark green"</value>
+ </param>
+ <param>
+ <key>alpha9</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>label10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>width10</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>color10</key>
+ <value>"dark blue"</value>
+ </param>
+ <param>
+ <key>alpha10</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(728, 416)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>bp_filter</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>2</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_0</source_block_id>
+ <sink_block_id>bp_filter</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>hp_filter</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>1</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_0</source_block_id>
+ <sink_block_id>hp_filter</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>lp_filter</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_0</source_block_id>
+ <sink_block_id>lp_filter</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_0</source_block_id>
+ <sink_block_id>br_filter</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>br_filter</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>3</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>rrc_filter</source_block_id>
+ <sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>4</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>analog_fastnoise_source_x_0</source_block_id>
+ <sink_block_id>rrc_filter</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt
index 575f6675d6..b3bc2e1828 100644
--- a/gr-filter/grc/CMakeLists.txt
+++ b/gr-filter/grc/CMakeLists.txt
@@ -45,6 +45,11 @@ install(FILES
filter_band_pass_filter.xml
filter_band_reject_filter.xml
filter_root_raised_cosine_filter.xml
+ variable_low_pass_filter_taps.xml
+ variable_high_pass_filter_taps.xml
+ variable_band_pass_filter_taps.xml
+ variable_band_reject_filter_taps.xml
+ variable_rrc_filter_taps.xml
DESTINATION ${GRC_BLOCKS_DIR}
COMPONENT "filter_python"
)
diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml
index fbba9daf09..ea869a75bd 100644
--- a/gr-filter/grc/filter_block_tree.xml
+++ b/gr-filter/grc/filter_block_tree.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright 2012 Free Software Foundation, Inc.
+ Copyright 2012,2015 Free Software Foundation, Inc.
This file is part of GNU Radio
@@ -30,6 +30,12 @@
<name></name> <!-- Blank for Root Name -->
<cat>
<name>Filters</name>
+ <!-- FIR filter tap generators -->
+ <block>variable_low_pass_filter_taps</block>
+ <block>variable_high_pass_filter_taps</block>
+ <block>variable_band_pass_filter_taps</block>
+ <block>variable_band_reject_filter_taps</block>
+ <block>variable_rrc_filter_taps</block>
<!-- FIR convenience filters -->
<block>low_pass_filter</block>
<block>high_pass_filter</block>
diff --git a/gr-filter/grc/variable_band_pass_filter_taps.xml b/gr-filter/grc/variable_band_pass_filter_taps.xml
new file mode 100644
index 0000000000..6cdfcc0373
--- /dev/null
+++ b/gr-filter/grc/variable_band_pass_filter_taps.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<!--
+#######################################################
+# Convenience wrapper for calling firdes.band_pass(...)
+# or firdes.complex_bandpass(...)
+#######################################################
+ -->
+<block>
+ <name>Band-pass Filter Taps</name>
+ <key>variable_band_pass_filter_taps</key>
+ <import>from gnuradio.filter import firdes</import>
+ <var_make>
+self.$(id) = $(id) = firdes.$(type.fcn)($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta)
+ </var_make>
+ <var_value>firdes.$(type.fcn)($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta)</var_value>
+ <make></make>
+
+ <param>
+ <name>Tap Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Real</name>
+ <key>taps_real</key>
+ <opt>fcn:band_pass</opt>
+ </option>
+ <option>
+ <name>Complex</name>
+ <key>taps_complex</key>
+ <opt>fcn:complex_band_pass</opt>
+ </option>
+ </param>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Sample Rate (Hz)</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Low Cutoff Freq (Hz)</name>
+ <key>low_cutoff_freq</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>High Cutoff Freq (Hz)</name>
+ <key>high_cutoff_freq</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Transition Width (Hz)</name>
+ <key>width</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>float</type>
+ </param>
+ <doc>
+ This is a convenience wrapper for calling firdes.band_pass() or firdes.complex_band_pass()
+
+ The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/gr-filter/grc/variable_band_reject_filter_taps.xml b/gr-filter/grc/variable_band_reject_filter_taps.xml
new file mode 100644
index 0000000000..fbf25886d3
--- /dev/null
+++ b/gr-filter/grc/variable_band_reject_filter_taps.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0"?>
+<!--
+#########################################################
+# Convenience wrapper for calling firdes.band_reject(...)
+#########################################################
+ -->
+<block>
+ <name>Band-reject Filter Taps</name>
+ <key>variable_band_reject_filter_taps</key>
+ <import>from gnuradio.filter import firdes</import>
+ <var_make>
+self.$(id) = $(id) = firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta)
+ </var_make>
+ <var_value>firdes.band_reject($gain, $samp_rate, $low_cutoff_freq, $high_cutoff_freq, $width, $win, $beta)</var_value>
+ <make></make>
+
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Sample Rate (Hz)</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Low Cutoff Freq (Hz)</name>
+ <key>low_cutoff_freq</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>High Cutoff Freq (Hz)</name>
+ <key>high_cutoff_freq</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Transition Width (Hz)</name>
+ <key>width</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>float</type>
+ </param>
+ <doc>
+ This is a convenience wrapper for calling firdes.band_reject().
+
+ The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/gr-filter/grc/variable_high_pass_filter_taps.xml b/gr-filter/grc/variable_high_pass_filter_taps.xml
new file mode 100644
index 0000000000..08768d808a
--- /dev/null
+++ b/gr-filter/grc/variable_high_pass_filter_taps.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+######################################################
+## Convenience wrapper around call to fides.high_pass()
+######################################################
+ -->
+<block>
+ <name>High-pass Filter Taps</name>
+ <key>variable_high_pass_filter_taps</key>
+ <import>from gnuradio.filter import firdes</import>
+ <var_make>
+self.$(id) = $(id) = firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta)
+ </var_make>
+ <var_value>firdes.high_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta)</var_value>
+ <make></make>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Sample Rate (Hz)</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Cutoff Freq (Hz)</name>
+ <key>cutoff_freq</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Transition Width (Hz)</name>
+ <key>width</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>float</type>
+ </param>
+ <doc>
+ This variable is a convenience wrapper around a call to firdes.high_pass(...).
+
+ The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/gr-filter/grc/variable_low_pass_filter_taps.xml b/gr-filter/grc/variable_low_pass_filter_taps.xml
new file mode 100644
index 0000000000..e3367b1ec5
--- /dev/null
+++ b/gr-filter/grc/variable_low_pass_filter_taps.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<!--
+######################################################
+## Convenience wrapper around call to fides.low_pass()
+######################################################
+ -->
+<block>
+ <name>Low-pass Filter Taps</name>
+ <key>variable_low_pass_filter_taps</key>
+ <import>from gnuradio.filter import firdes</import>
+ <var_make>
+self.$(id) = $(id) = firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta)
+ </var_make>
+ <var_value>firdes.low_pass($gain, $samp_rate, $cutoff_freq, $width, $win, $beta)</var_value>
+ <make></make>
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Sample Rate (Hz)</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Cutoff Freq (Hz)</name>
+ <key>cutoff_freq</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Transition Width (Hz)</name>
+ <key>width</key>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Window</name>
+ <key>win</key>
+ <value>firdes.WIN_HAMMING</value>
+ <type>int</type>
+ <option>
+ <name>Hamming</name>
+ <key>firdes.WIN_HAMMING</key>
+ </option>
+ <option>
+ <name>Hann</name>
+ <key>firdes.WIN_HANN</key>
+ </option>
+ <option>
+ <name>Blackman</name>
+ <key>firdes.WIN_BLACKMAN</key>
+ </option>
+ <option>
+ <name>Rectangular</name>
+ <key>firdes.WIN_RECTANGULAR</key>
+ </option>
+ <option>
+ <name>Kaiser</name>
+ <key>firdes.WIN_KAISER</key>
+ </option>
+ </param>
+ <param>
+ <name>Beta</name>
+ <key>beta</key>
+ <value>6.76</value>
+ <type>float</type>
+ </param>
+ <doc>
+ This variable is a convenience wrapper around a call to firdes.low_pass(...).
+
+ The beta paramater only applies to the Kaiser window.
+ </doc>
+</block>
diff --git a/gr-filter/grc/variable_rrc_filter_taps.xml b/gr-filter/grc/variable_rrc_filter_taps.xml
new file mode 100644
index 0000000000..2824ba75b2
--- /dev/null
+++ b/gr-filter/grc/variable_rrc_filter_taps.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+########################################################################
+## Convenience wrapper for calling firdes.root_raised_cosine_filter(...)
+########################################################################
+ -->
+<block>
+ <name>RRC Filter Taps</name>
+ <key>variable_rrc_filter_taps</key>
+ <import>from gnuradio.filter import firdes</import>
+ <var_make>
+self.$(id) = $(id) = firdes.root_raised_cosine($gain, $samp_rate, $sym_rate, $alpha, $ntaps)
+ </var_make>
+ <var_value>firdes.root_raised_cosine($gain, $samp_rate, $sym_rate, $alpha, $ntaps)</var_value>
+ <make></make>
+
+ <param>
+ <name>Gain</name>
+ <key>gain</key>
+ <value>1.0</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Sample Rate (Hz)</name>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Symbol Rate (Hz)</name>
+ <key>sym_rate</key>
+ <value></value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Excess BW</name>
+ <key>alpha</key>
+ <value>0.35</value>
+ <type>float</type>
+ </param>
+ <param>
+ <name>Num Taps</name>
+ <key>ntaps</key>
+ <value>11*sps</value>
+ <type>int</type>
+ </param>
+ <doc>
+ This is a convenience wrapper for calling firdes.root_raised_cosine(...).
+ </doc>
+</block>
diff --git a/gr-qtgui/grc/qtgui_range.xml b/gr-qtgui/grc/qtgui_range.xml
index 05f3ffce9f..71b614cc5e 100644
--- a/gr-qtgui/grc/qtgui_range.xml
+++ b/gr-qtgui/grc/qtgui_range.xml
@@ -6,105 +6,126 @@
###################################################
-->
<block>
- <name>QT GUI Range</name>
- <key>variable_qtgui_range</key>
- <import>from gnuradio.qtgui import Range, RangeWidget</import>
- <var_make>self.$(id) = $(id) = $value</var_make>
- <make>#set $win = 'self._%s_win'%$id
+ <name>QT GUI Range</name>
+ <key>variable_qtgui_range</key>
+ <import>from gnuradio.qtgui import Range, RangeWidget</import>
+ <var_make>self.$(id) = $(id) = $value</var_make>
+ <make>#set $win = 'self._%s_win'%$id
#set $range = 'self._%s_range'%$id
#if not $label()
#set $label = '"%s"'%$id
#end if
$(range) = Range($start, $stop, $step, $value, $min_len)
-$(win) = RangeWidget($range, self.set_$(id), $label, "$widget")
+$(win) = RangeWidget($range, self.set_$(id), $label, "$widget", $rangeType)
$(gui_hint()($win))</make>
- <callback>self.set_$(id)($value)</callback>
- <param>
- <name>Label</name>
- <key>label</key>
- <value></value>
- <type>string</type>
- <hide>#if $label() then 'none' else 'part'#</hide>
- </param>
- <param>
- <name>Default Value</name>
- <key>value</key>
- <value>50</value>
- <type>real</type>
- </param>
- <param>
- <name>Start</name>
- <key>start</key>
- <value>0</value>
- <type>real</type>
- </param>
- <param>
- <name>Stop</name>
- <key>stop</key>
- <value>100</value>
- <type>real</type>
- </param>
- <param>
- <name>Step</name>
- <key>step</key>
- <value>1</value>
- <type>real</type>
- </param>
- <param>
- <name>Widget</name>
- <key>widget</key>
- <value>counter_slider</value>
- <type>enum</type>
- <hide>part</hide>
- <option><name>Counter + Slider</name><key>counter_slider</key></option>
- <option><name>Counter</name><key>counter</key></option>
- <option><name>Slider</name><key>slider</key></option>
- <option><name>Knob</name><key>dial</key></option>
- </param>
- <param>
- <name>Orientation</name>
- <key>orient</key>
- <value>Qt.Horizontal</value>
- <type>enum</type>
- <hide>#if $widget() == "slider" then 'part' else 'all'#</hide>
- <option>
- <name>Horizontal</name>
- <key>Qt.Horizontal</key>
- <opt>scalepos:BottomScale</opt>
- <opt>minfcn:setMinimumWidth</opt>
- </option>
- <option>
- <name>Vertical</name>
- <key>Qt.Vertical</key>
- <opt>scalepos:LeftScale</opt>
- <opt>minfcn:setMinimumHeight</opt>
- </option>
- </param>
- <param>
- <name>Minimum Length</name>
- <key>min_len</key>
- <value>200</value>
- <type>int</type>
- <hide>part</hide>
- </param>
-<!-- from min_len <hide>#if $widget().split('_')[0] in ("slider", "counter") then 'part' else 'all'#</hide>-->
- <param>
- <name>GUI Hint</name>
- <key>gui_hint</key>
- <value></value>
- <type>gui_hint</type>
- <hide>part</hide>
- </param>
- <check>$start &lt;= $value &lt;= $stop</check>
- <check>$start &lt; $stop</check>
- <doc>
-This block creates a variable with a slider. \
-Leave the label blank to use the variable id as the label. \
-The value must be a real number. \
-The value must be between the start and the stop.
+ <callback>self.set_$(id)($value)</callback>
-The GUI hint can be used to position the widget within the application. \
-The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
-Both the tab specification and the grid position are optional.
- </doc>
+ <param>
+ <name>Label</name>
+ <key>label</key>
+ <value></value>
+ <type>string</type>
+ <hide>#if $label() then 'none' else 'part'#</hide>
+ </param>
+
+ <param>
+ <name>Type</name>
+ <key>rangeType</key>
+ <value>"float"</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option><name>Float</name><key>float</key><opt>type:float</opt></option>
+ <option><name>Int</name><key>int</key><opt>type:int</opt></option>
+ </param>
+
+ <param>
+ <name>Default Value</name>
+ <key>value</key>
+ <value>50</value>
+ <type>$rangeType.type</type>
+ </param>
+
+ <param>
+ <name>Start</name>
+ <key>start</key>
+ <value>0</value>
+ <type>$rangeType.type</type>
+ </param>
+
+ <param>
+ <name>Stop</name>
+ <key>stop</key>
+ <value>100</value>
+ <type>$rangeType.type</type>
+ </param>
+
+ <param>
+ <name>Step</name>
+ <key>step</key>
+ <value>1</value>
+ <type>$rangeType.type</type>
+ </param>
+
+ <param>
+ <name>Widget</name>
+ <key>widget</key>
+ <value>counter_slider</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option><name>Counter + Slider</name><key>counter_slider</key></option>
+ <option><name>Counter</name><key>counter</key></option>
+ <option><name>Slider</name><key>slider</key></option>
+ <option><name>Knob</name><key>dial</key></option>
+ </param>
+
+ <param>
+ <name>Orientation</name>
+ <key>orient</key>
+ <value>Qt.Horizontal</value>
+ <type>enum</type>
+ <hide>#if $widget() == "slider" then 'part' else 'all'#</hide>
+ <option>
+ <name>Horizontal</name>
+ <key>Qt.Horizontal</key>
+ <opt>scalepos:BottomScale</opt>
+ <opt>minfcn:setMinimumWidth</opt>
+ </option>
+ <option>
+ <name>Vertical</name>
+ <key>Qt.Vertical</key>
+ <opt>scalepos:LeftScale</opt>
+ <opt>minfcn:setMinimumHeight</opt>
+ </option>
+ </param>
+
+ <param>
+ <name>Minimum Length</name>
+ <key>min_len</key>
+ <value>200</value>
+ <type>int</type>
+ <hide>part</hide>
+ </param>
+ <!-- from min_len <hide>#if $widget().split('_')[0] in ("slider", "counter") then 'part' else 'all'#</hide>-->
+
+ <param>
+ <name>GUI Hint</name>
+ <key>gui_hint</key>
+ <value></value>
+ <type>gui_hint</type>
+ <hide>part</hide>
+ </param>
+
+ <check>$start &lt;= $value &lt;= $stop</check>
+ <check>$start &lt; $stop</check>
+
+ <doc>
+ This block creates a variable with a slider. \
+ Leave the label blank to use the variable id as the label. \
+ The value must be a real number. \
+ The value must be between the start and the stop.
+
+ The GUI hint can be used to position the widget within the application. \
+ The hint is of the form [tab_id@tab_index]: [row, col, row_span, col_span]. \
+ Both the tab specification and the grid position are optional.
+ </doc>
</block>
diff --git a/gr-qtgui/lib/vector_sink_f_impl.cc b/gr-qtgui/lib/vector_sink_f_impl.cc
index 0644071ebc..ba139b97f4 100644
--- a/gr-qtgui/lib/vector_sink_f_impl.cc
+++ b/gr-qtgui/lib/vector_sink_f_impl.cc
@@ -157,7 +157,7 @@ namespace gr {
d_main_gui->setVecSize(d_vlen);
set_x_axis(x_start, x_step);
- if(not name.empty())
+ if(! name.empty())
set_title(name);
set_x_axis_label(x_axis_label);
set_y_axis_label(y_axis_label);
@@ -203,7 +203,7 @@ namespace gr {
void
vector_sink_f_impl::set_vec_average(const float avg)
{
- if (avg < 0 or avg > 1.0) {
+ if (avg < 0 || avg > 1.0) {
GR_LOG_ALERT(d_logger, "Invalid average value received in set_vec_average(), must be within [0, 1].");
return;
}
diff --git a/gr-qtgui/python/qtgui/range.py b/gr-qtgui/python/qtgui/range.py
index 168e6662c3..3eafc9002e 100755
--- a/gr-qtgui/python/qtgui/range.py
+++ b/gr-qtgui/python/qtgui/range.py
@@ -64,13 +64,16 @@ class Range(object):
class RangeWidget(QtGui.QWidget):
- def __init__(self, ranges, slot, label, style):
+ def __init__(self, ranges, slot, label, style, rangeType=float):
""" Creates the QT Range widget """
QtGui.QWidget.__init__(self)
self.range = ranges
self.style = style
+ # rangeType tells the block how to return the value as a standard
+ self.rangeType = rangeType
+
# Top-block function to call when any value changes
# Some widgets call this directly when their value changes.
# Others have intermediate functions to map the value into the right range.
@@ -81,24 +84,26 @@ class RangeWidget(QtGui.QWidget):
layout.addWidget(label)
if style == "dial":
- self.d_widget = self.Dial(self, self.range, self.notifyChanged)
+ self.d_widget = self.Dial(self, self.range, self.notifyChanged, rangeType)
elif style == "slider":
- self.d_widget = self.Slider(self, self.range, self.notifyChanged)
+ self.d_widget = self.Slider(self, self.range, self.notifyChanged, rangeType)
elif style == "counter":
# The counter widget can be directly wired to the notifyChanged slot
- self.d_widget = self.Counter(self, self.range, self.notifyChanged)
+ self.d_widget = self.Counter(self, self.range, self.notifyChanged, rangeType)
else:
# The CounterSlider needs its own internal handlers before calling notifyChanged
- self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged)
+ self.d_widget = self.CounterSlider(self, self.range, self.notifyChanged, rangeType)
layout.addWidget(self.d_widget)
self.setLayout(layout)
class Dial(QtGui.QDial):
""" Creates the range using a dial """
- def __init__(self, parent, ranges, slot):
+ def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QDial.__init__(self, parent)
+ self.rangeType = rangeType
+
# Setup the dial
self.setRange(0, ranges.nsteps-1)
self.setSingleStep(1)
@@ -116,13 +121,15 @@ class RangeWidget(QtGui.QWidget):
def changed(self, value):
""" Handles maping the value to the right range before calling the slot. """
val = self.range.map_range(value)
- self.notifyChanged(val)
+ self.notifyChanged(self.rangeType(val))
class Slider(QtGui.QSlider):
""" Creates the range using a slider """
- def __init__(self, parent, ranges, slot):
+ def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QSlider.__init__(self, QtCore.Qt.Horizontal, parent)
+ self.rangeType = rangeType
+
# Setup the slider
#self.setFocusPolicy(QtCore.Qt.NoFocus)
self.setRange(0, ranges.nsteps - 1)
@@ -149,7 +156,7 @@ class RangeWidget(QtGui.QWidget):
def changed(self, value):
""" Handle the valueChanged signal and map the value into the correct range """
val = self.range.map_range(value)
- self.notifyChanged(val)
+ self.notifyChanged(self.rangeType(val))
def mousePressEvent(self, event):
if((event.button() == QtCore.Qt.LeftButton)):
@@ -168,9 +175,11 @@ class RangeWidget(QtGui.QWidget):
class Counter(QtGui.QDoubleSpinBox):
""" Creates the range using a counter """
- def __init__(self, parent, ranges, slot):
+ def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QDoubleSpinBox.__init__(self, parent)
+ self.rangeType = rangeType
+
# Setup the counter
self.setRange(ranges.min, ranges.max)
self.setValue(ranges.default)
@@ -179,18 +188,25 @@ class RangeWidget(QtGui.QWidget):
self.setDecimals(ranges.precision)
# The counter already handles floats and can be connected directly.
- self.valueChanged.connect(slot)
+ self.valueChanged.connect(self.changed)
+ self.notifyChanged = slot
+
+ def changed(self, value):
+ """ Handle the valueChanged signal by converting to the right type """
+ self.notifyChanged(self.rangeType(value))
class CounterSlider(QtGui.QWidget):
""" Creates the range using a counter and slider """
- def __init__(self, parent, ranges, slot):
+ def __init__(self, parent, ranges, slot, rangeType=float):
QtGui.QWidget.__init__(self, parent)
+ self.rangeType = rangeType
+
# Slot to call in the parent
self.notifyChanged = slot
- self.slider = RangeWidget.Slider(parent, ranges, self.sliderChanged)
- self.counter = RangeWidget.Counter(parent, ranges, self.counterChanged)
+ self.slider = RangeWidget.Slider(parent, ranges, self.sliderChanged, rangeType)
+ self.counter = RangeWidget.Counter(parent, ranges, self.counterChanged, rangeType)
# Need another horizontal layout to wrap the other widgets.
layout = Qt.QHBoxLayout()
@@ -207,8 +223,8 @@ class RangeWidget(QtGui.QWidget):
# If the counter was changed, ignore any of these events
if not self.ignoreSlider:
# Value is already float. Just set the counter
- self.counter.setValue(value)
- self.notifyChanged(value)
+ self.counter.setValue(self.rangeType(value))
+ self.notifyChanged(self.rangeType(value))
self.ignoreSlider = False
def counterChanged(self, value):
@@ -223,4 +239,21 @@ class RangeWidget(QtGui.QWidget):
self.ignoreSlider = True
self.slider.setValue(new)
- self.notifyChanged(value)
+ self.notifyChanged(self.rangeType(value))
+
+
+if __name__ == "__main__":
+ from PyQt4 import Qt
+ import sys
+
+ def valueChanged(frequency):
+ print("Value updated - " + str(frequency))
+
+ app = Qt.QApplication(sys.argv)
+ widget = RangeWidget(Range(0, 100, 10, 1, 100), valueChanged, "Test", "counter_slider", int)
+
+ widget.show()
+ widget.setWindowTitle("Test Qt Range")
+ app.exec_()
+
+ widget = None
diff --git a/gr-uhd/doc/uhd.dox b/gr-uhd/doc/uhd.dox
index da6d9d45f5..27a1475566 100644
--- a/gr-uhd/doc/uhd.dox
+++ b/gr-uhd/doc/uhd.dox
@@ -12,15 +12,10 @@ as:
from gnuradio import uhd
\endcode
-The relevant blocks are listed in the \ref uhd_blk group.
-
-A quick listing of the details can be found in Python after importing
-by using:
-
-\code
- help(uhd)
-\endcode
-
+The relevant blocks are listed in the \ref uhd_blk group. The most important
+components are the gr::uhd::usrp_source and gr::uhd::usrp_sink blocks, which
+act as receivers/transmitters. Both are derived from gr::uhd::usrp_block, which
+defines many of the shared functions between those blocks.
\section uhd_external_docs External Documentation
@@ -36,48 +31,92 @@ http://files.ettus.com/manual/annotated.html
\section uhd_command_syntax Command Syntax
The UHD sink and source can be controlled by a message port. These message ports
-take commands, which are PMTs formatted as such:
+take commands, which are PMTs formatted as described in \ref msg_passing_commands.
+
+There is a legacy format, which will be deprecated in the future, where commands may
+be tuples, formatted as:
(command, value, [channel])
-A command PMT is either a pair or a tuple. If it's a tuple, it must have either 2 or 3 elements.
-Any other type of PMT will throw an error.
+See older versions of this manual for documentation on this deprecated command format.
-The `command` part is a string, which defines the command. `value` is a PMT whose format depends
-on the command issued. Finally, `channel` is an integer PMT value that specifies which channel
-this command shall be specified on. If this value is omitted, then it either applies this command
-to all channels or channel zero, depending on which command is used.
+In general, every command consists of one or more key/value pairs (either stored as a
+PMT pair, or a dictionary). A full list of keys is listed below.
Example:
\code{.cpp}
-pmt::pmt_t command = pmt::cons( // We make a pair, but pmt::make_tuple() is also valid!
- pmt::mp("freq"), // Use the 'freq' command, which sets the frequency
+pmt::pmt_t command = pmt::cons( // Make a pair
+ pmt::mp("freq"), // Key is 'freq' => sets the frequency
pmt::mp(1.1e9) // Set the frequency to 1.1 GHz
);
+// Now pass 'command' into the USRP block's command port
\endcode
This PMT would set the frequency to 1.1 GHz on all channels. We make use of the pmt::mp() function
which automatically sets the PMT types. Assume we only want to set the frequency on channel 1
-(i.e. the second channel). In this case, we must construct a tuple:
+(i.e. the second channel). In this case, we must construct a dictionary:
\code{.cpp}
-pmt::pmt_t command = pmt::make_tuple(
- pmt::mp("freq"), // Use the 'freq' command, which sets the frequency
- pmt::mp(1.1e9) // Set the frequency to 1.1 GHz
- pmt::mp(1) // Select channel 1
-);
+pmt::pmt_t command = pmt::make_dict();
+pmt::dict_add(command, pmt::mp("freq"), pmt::mp(1.1e9)); // Specify frequency
+pmt::dict_add(command, pmt::mp("chan"), pmt::mp(1)); // Specify channel
+// Now pass 'command' into the USRP block's command port
\endcode
+This command structure becomes more intuitive when thinking of sending the command PMT
+as a function call, where the key/value pairs are argument names and values, respectively.
+In the above example, the behaviour is the same as if calling
+\code{.python}
+usrp_source.set_center_freq(freq=1.1e9, chan=1)
+\endcode
+The main difference is that we can add more properties to the same
+command PMT, e.g. as such:
+\code{.cpp}
+// 'command' is the same PMT as in the previous example
+pmt::dict_add(command, pmt::mp("gain"), pmt::mp(23.0)); // Specify gain
+pmt::dict_add(command, pmt::mp("antenna"), pmt::mp("TX/RX")); // Switch antenna
+// Now pass 'command' into the USRP block's command port
+\endcode
+When the USRP block interprets this command PMT, all properties will be
+set.
+
+
+\subsection uhd_command_syntax_cmds Common command keys
+
+The following command keys are understood by both UHD Source and Sink:
+
+Command name | Value Type | Description
+-------------|--------------|-------------------------------------------------------------
+`chan` | int | Specifies a channel. If this is not given, either all channels are chosen, or channel 0, depending on the action. A value of -1 forces 'all channels', where possible.
+`gain` | double | Sets the Tx or Rx gain (in dB). Defaults to all channels.
+`freq` | double | Sets the Tx or Rx frequency. Defaults to all channels. If specified without `lo_offset`, it will set the LO offset to zero.
+`lo_offset` | double | Sets an LO offset. Defaults to all channels. Note this does not affect the effective center frequency.
+`tune` | tune_request | Like freq, but sets a full tune request (i.e. center frequency and DSP offset). Defaults to all channels.
+`lo_freq` | double | For fully manual tuning: Set the LO frequency (RF frequency). Conflicts with `freq`, `lo_offset`, and `tune`.
+`dsp_freq` | double | For fully manual tuning: Set the DSP frequency (CORDIC frequency). Conflicts with `freq`, `lo_offset`, and `tune`.
+`rate` | double | See usrp_block::set_samp_rate(). *Always* affects all channels.
+`bandwidth` | double | See usrp_block::set_bandwidth(). Defaults to all channels.
+`time` | timestamp | Sets a command time. See usrp_block::set_command_time(). A value of PMT_NIL will clear the command time.
+`mboard` | int | Specify mboard index, where applicable.
+`antenna` | string | See usrp_block::set_antenna(). Defaults to all channels.
+
+Special types:
+
+- tune_request: Like a uhd::tune_request_t, but always uses POLICY_AUTO. This is a pair, composed of (target_frequency, lo_offset)
+- timestamp: A pair composed of (long full_secs, double frac_secs). Similar to uhd::time_spec_t
-\subsection uhd_command_syntax_cmds Common commands
+\b Note: Not all commands are affected by `time`. See the UHD manual for details on timed commands.
-The following commands are understood by both UHD Source and Sink:
+\subsection uhd_command_syntax_multi_vs_single Dictionaries vs pairs
-Command name | Value Type | Description
--------------|------------|-------------------------------------------------------------
-`freq` | double | Sets the Tx or Rx frequency. Defaults to all channels.
-`lo_offset` | double | Sets an LO offset. Defaults to all channels.
-`gain` | double | Sets the Tx or Rx gain (in dB). Defaults to all channels.
+Given the choices, it may be unclear if it's preferable to send multiple commands
+to the USRP block with a single key/value pair each, or send a single dict with
+all the values.
+In general, the dictionary should be preferred. It has some distinct advantages:
+- If it carries a timestamp, this timestamp is valid for all key/value pairs it
+ may be applied to.
+- All settings will be applied at once. With multiple messages, other blocks might
+ be sending interfering messages while the messages are being processed.
\section uhd_configuring Configuring a UHD object
diff --git a/gr-uhd/examples/grc/uhd_msg_tune.grc b/gr-uhd/examples/grc/uhd_msg_tune.grc
index 89022278be..cedb743b40 100644
--- a/gr-uhd/examples/grc/uhd_msg_tune.grc
+++ b/gr-uhd/examples/grc/uhd_msg_tune.grc
@@ -1,39 +1,56 @@
<?xml version='1.0' encoding='ASCII'?>
+<?grc format='1' created='3.7.8'?>
<flow_graph>
<timestamp>Tue Jul 8 12:08:19 2014</timestamp>
<block>
<key>options</key>
<param>
- <key>id</key>
- <value>uhd_tune_msg</value>
+ <key>author</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>title</key>
- <value>UHD Message Tuner</value>
+ <key>category</key>
+ <value>Custom</value>
</param>
<param>
- <key>author</key>
+ <key>comment</key>
<value></value>
</param>
<param>
<key>description</key>
- <value>Tune a UHD source from a QT sink via messages.</value>
+ <value>Tune a UHD source from a QT sink via messages (double-click a frequency to tune)</value>
</param>
<param>
- <key>window_size</key>
- <value>1280, 1024</value>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 3)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
<key>generate_options</key>
<value>qt_gui</value>
</param>
<param>
- <key>category</key>
- <value>Custom</value>
+ <key>id</key>
+ <value>uhd_tune_msg</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
</param>
<param>
<key>run_options</key>
@@ -44,447 +61,708 @@
<value>True</value>
</param>
<param>
- <key>max_nouts</key>
- <value>0</value>
+ <key>thread_safe_setters</key>
+ <value></value>
</param>
<param>
- <key>realtime_scheduling</key>
- <value></value>
+ <key>title</key>
+ <value>UHD Message Tuner</value>
</param>
<param>
- <key>alias</key>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_qtgui_chooser</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>value</key>
+ <value>TX/RX</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(-1, -2)</value>
+ <value>(8, 307)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value></value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>ant_msg</value>
+ </param>
+ <param>
+ <key>label0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Antenna</value>
+ </param>
+ <param>
+ <key>labels</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>num_opts</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>option0</key>
+ <value>TX/RX</value>
+ </param>
+ <param>
+ <key>option1</key>
+ <value>RX2</value>
+ </param>
+ <param>
+ <key>option2</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>option3</key>
+ <value>3</value>
+ </param>
+ <param>
+ <key>option4</key>
+ <value>4</value>
+ </param>
+ <param>
+ <key>options</key>
+ <value>[0, 1, 2]</value>
+ </param>
+ <param>
+ <key>orient</key>
+ <value>Qt.QVBoxLayout</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>string</value>
+ </param>
+ <param>
+ <key>widget</key>
+ <value>combo_box</value>
+ </param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>initial_fc</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
+ <key>_coordinate</key>
+ <value>(232, 115)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>cmd_msg</value>
+ </param>
+ <param>
<key>value</key>
- <value>100e6</value>
+ <value>pmt.to_pmt({'antenna': ant_msg, 'gain': gain_msg, 'chan': 0, 'freq': freq_msg, 'lo_offset': lo_msg})</value>
</param>
+ </block>
+ <block>
+ <key>variable_qtgui_entry</key>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>value</key>
+ <value>initial_fc</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(-2, 172)</value>
+ <value>(144, 227)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>0,1,1,1</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>freq_msg</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Frequency</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>real</value>
+ </param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>samp_rate</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
+ <key>_coordinate</key>
+ <value>(104, 99)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>gain</value>
+ </param>
+ <param>
<key>value</key>
- <value>2e6</value>
+ <value>0.8</value>
</param>
+ </block>
+ <block>
+ <key>variable_qtgui_entry</key>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>value</key>
+ <value>gain</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(1, 102)</value>
+ <value>(8, 227)</value>
+ </param>
+ <param>
+ <key>gui_hint</key>
+ <value>0,0,1,1</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>gain_msg</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>Gain</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>real</value>
+ </param>
</block>
<block>
- <key>variable_qtgui_range</key>
+ <key>variable</key>
<param>
- <key>id</key>
- <value>gain</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>label</key>
- <value></value>
+ <key>_coordinate</key>
+ <value>(8, 163)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>initial_fc</value>
</param>
<param>
<key>value</key>
- <value>20</value>
+ <value>100e6</value>
</param>
+ </block>
+ <block>
+ <key>variable_qtgui_entry</key>
<param>
- <key>start</key>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>value</key>
<value>0</value>
</param>
<param>
- <key>stop</key>
- <value>60</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>step</key>
- <value>1</value>
+ <key>_coordinate</key>
+ <value>(144, 307)</value>
</param>
<param>
- <key>widget</key>
- <value>counter_slider</value>
+ <key>gui_hint</key>
+ <value>1,1,1,1</value>
</param>
<param>
- <key>orient</key>
- <value>Qt.Horizontal</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>min_len</key>
- <value>200</value>
+ <key>id</key>
+ <value>lo_msg</value>
</param>
<param>
- <key>gui_hint</key>
- <value></value>
+ <key>label</key>
+ <value>LO Offset</value>
</param>
<param>
- <key>alias</key>
+ <key>type</key>
+ <value>real</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(103, 99)</value>
+ <value>(8, 99)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>2e6</value>
+ </param>
</block>
<block>
- <key>uhd_usrp_source</key>
+ <key>blocks_message_strobe</key>
<param>
- <key>id</key>
- <value>uhd_usrp_source_0</value>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>type</key>
- <value>fc32</value>
+ <key>_coordinate</key>
+ <value>(216, 43)</value>
</param>
<param>
- <key>otw</key>
- <value></value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>stream_args</key>
- <value></value>
+ <key>id</key>
+ <value>blocks_message_strobe_0</value>
</param>
<param>
- <key>stream_chans</key>
- <value>[]</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>dev_addr</key>
- <value>""</value>
+ <key>msg</key>
+ <value>cmd_msg</value>
</param>
<param>
- <key>dev_args</key>
- <value>""</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>sync</key>
- <value></value>
+ <key>period</key>
+ <value>2000</value>
</param>
+ </block>
+ <block>
+ <key>qtgui_freq_sink_x</key>
<param>
- <key>clock_rate</key>
- <value>0.0</value>
+ <key>autoscale</key>
+ <value>False</value>
</param>
<param>
- <key>num_mboards</key>
- <value>1</value>
+ <key>average</key>
+ <value>0.1</value>
</param>
<param>
- <key>clock_source0</key>
- <value></value>
+ <key>bw</key>
+ <value>samp_rate</value>
</param>
<param>
- <key>time_source0</key>
+ <key>alias</key>
<value></value>
</param>
<param>
- <key>sd_spec0</key>
- <value></value>
+ <key>fc</key>
+ <value>initial_fc</value>
</param>
<param>
- <key>clock_source1</key>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>time_source1</key>
- <value></value>
+ <key>ctrlpanel</key>
+ <value>False</value>
</param>
<param>
- <key>sd_spec1</key>
+ <key>affinity</key>
<value></value>
</param>
<param>
- <key>clock_source2</key>
- <value></value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>time_source2</key>
- <value></value>
+ <key>fftsize</key>
+ <value>1024</value>
</param>
<param>
- <key>sd_spec2</key>
- <value></value>
+ <key>_coordinate</key>
+ <value>(472, 155)</value>
</param>
<param>
- <key>clock_source3</key>
+ <key>gui_hint</key>
<value></value>
</param>
<param>
- <key>time_source3</key>
- <value></value>
+ <key>_rotation</key>
+ <value>180</value>
</param>
<param>
- <key>sd_spec3</key>
- <value></value>
+ <key>grid</key>
+ <value>True</value>
</param>
<param>
- <key>clock_source4</key>
- <value></value>
+ <key>id</key>
+ <value>qtgui_freq_sink_x_0</value>
</param>
<param>
- <key>time_source4</key>
- <value></value>
+ <key>legend</key>
+ <value>False</value>
</param>
<param>
- <key>sd_spec4</key>
- <value></value>
+ <key>alpha1</key>
+ <value>1.0</value>
</param>
<param>
- <key>clock_source5</key>
- <value></value>
+ <key>color1</key>
+ <value>"blue"</value>
</param>
<param>
- <key>time_source5</key>
+ <key>label1</key>
<value></value>
</param>
<param>
- <key>sd_spec5</key>
- <value></value>
+ <key>width1</key>
+ <value>1</value>
</param>
<param>
- <key>clock_source6</key>
- <value></value>
+ <key>alpha10</key>
+ <value>1.0</value>
</param>
<param>
- <key>time_source6</key>
- <value></value>
+ <key>color10</key>
+ <value>"dark blue"</value>
</param>
<param>
- <key>sd_spec6</key>
+ <key>label10</key>
<value></value>
</param>
<param>
- <key>clock_source7</key>
- <value></value>
+ <key>width10</key>
+ <value>1</value>
</param>
<param>
- <key>time_source7</key>
- <value></value>
+ <key>alpha2</key>
+ <value>1.0</value>
</param>
<param>
- <key>sd_spec7</key>
+ <key>color2</key>
+ <value>"red"</value>
+ </param>
+ <param>
+ <key>label2</key>
<value></value>
</param>
<param>
- <key>nchan</key>
+ <key>width2</key>
<value>1</value>
</param>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>alpha3</key>
+ <value>1.0</value>
</param>
<param>
- <key>center_freq0</key>
- <value>initial_fc</value>
+ <key>color3</key>
+ <value>"green"</value>
</param>
<param>
- <key>gain0</key>
- <value>gain</value>
+ <key>label3</key>
+ <value></value>
</param>
<param>
- <key>ant0</key>
+ <key>width3</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>alpha4</key>
+ <value>1.0</value>
+ </param>
+ <param>
+ <key>color4</key>
+ <value>"black"</value>
+ </param>
+ <param>
+ <key>label4</key>
<value></value>
</param>
<param>
- <key>bw0</key>
- <value>0</value>
+ <key>width4</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq1</key>
- <value>0</value>
+ <key>alpha5</key>
+ <value>1.0</value>
</param>
<param>
- <key>gain1</key>
- <value>0</value>
+ <key>color5</key>
+ <value>"cyan"</value>
</param>
<param>
- <key>ant1</key>
+ <key>label5</key>
<value></value>
</param>
<param>
- <key>bw1</key>
- <value>0</value>
+ <key>width5</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq2</key>
- <value>0</value>
+ <key>alpha6</key>
+ <value>1.0</value>
</param>
<param>
- <key>gain2</key>
- <value>0</value>
+ <key>color6</key>
+ <value>"magenta"</value>
</param>
<param>
- <key>ant2</key>
+ <key>label6</key>
<value></value>
</param>
<param>
- <key>bw2</key>
- <value>0</value>
+ <key>width6</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq3</key>
- <value>0</value>
+ <key>alpha7</key>
+ <value>1.0</value>
</param>
<param>
- <key>gain3</key>
- <value>0</value>
+ <key>color7</key>
+ <value>"yellow"</value>
</param>
<param>
- <key>ant3</key>
+ <key>label7</key>
<value></value>
</param>
<param>
- <key>bw3</key>
- <value>0</value>
+ <key>width7</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq4</key>
- <value>0</value>
+ <key>alpha8</key>
+ <value>1.0</value>
</param>
<param>
- <key>gain4</key>
- <value>0</value>
+ <key>color8</key>
+ <value>"dark red"</value>
</param>
<param>
- <key>ant4</key>
+ <key>label8</key>
<value></value>
</param>
<param>
- <key>bw4</key>
- <value>0</value>
+ <key>width8</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq5</key>
- <value>0</value>
+ <key>alpha9</key>
+ <value>1.0</value>
</param>
<param>
- <key>gain5</key>
- <value>0</value>
+ <key>color9</key>
+ <value>"dark green"</value>
</param>
<param>
- <key>ant5</key>
+ <key>label9</key>
<value></value>
</param>
<param>
- <key>bw5</key>
- <value>0</value>
+ <key>width9</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq6</key>
+ <key>maxoutbuf</key>
<value>0</value>
</param>
<param>
- <key>gain6</key>
+ <key>minoutbuf</key>
<value>0</value>
</param>
<param>
- <key>ant6</key>
+ <key>name</key>
<value></value>
</param>
<param>
- <key>bw6</key>
- <value>0</value>
+ <key>nconnections</key>
+ <value>1</value>
</param>
<param>
- <key>center_freq7</key>
- <value>0</value>
+ <key>showports</key>
+ <value>False</value>
</param>
<param>
- <key>gain7</key>
+ <key>freqhalf</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
<value>0</value>
</param>
<param>
- <key>ant7</key>
- <value></value>
+ <key>tr_level</key>
+ <value>0.0</value>
</param>
<param>
- <key>bw7</key>
- <value>0</value>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
</param>
<param>
- <key>center_freq8</key>
- <value>0</value>
+ <key>tr_tag</key>
+ <value>""</value>
</param>
<param>
- <key>gain8</key>
- <value>0</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>ant8</key>
+ <key>update_time</key>
+ <value>0.10</value>
+ </param>
+ <param>
+ <key>wintype</key>
+ <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ </param>
+ <param>
+ <key>ymax</key>
+ <value>-40</value>
+ </param>
+ <param>
+ <key>ymin</key>
+ <value>-120</value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_source</key>
+ <param>
+ <key>alias</key>
<value></value>
</param>
<param>
- <key>bw8</key>
- <value>0</value>
+ <key>ant0</key>
+ <value></value>
</param>
<param>
- <key>center_freq9</key>
+ <key>bw0</key>
<value>0</value>
</param>
<param>
- <key>gain9</key>
- <value>0</value>
+ <key>center_freq0</key>
+ <value>initial_fc</value>
</param>
<param>
- <key>ant9</key>
+ <key>norm_gain0</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>gain</value>
+ </param>
+ <param>
+ <key>ant10</key>
<value></value>
</param>
<param>
- <key>bw9</key>
+ <key>bw10</key>
<value>0</value>
</param>
<param>
@@ -492,15 +770,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain10</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain10</key>
<value>0</value>
</param>
<param>
- <key>ant10</key>
+ <key>ant11</key>
<value></value>
</param>
<param>
- <key>bw10</key>
+ <key>bw11</key>
<value>0</value>
</param>
<param>
@@ -508,15 +790,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain11</key>
<value>0</value>
</param>
<param>
- <key>ant11</key>
+ <key>ant12</key>
<value></value>
</param>
<param>
- <key>bw11</key>
+ <key>bw12</key>
<value>0</value>
</param>
<param>
@@ -524,15 +810,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain12</key>
<value>0</value>
</param>
<param>
- <key>ant12</key>
+ <key>ant13</key>
<value></value>
</param>
<param>
- <key>bw12</key>
+ <key>bw13</key>
<value>0</value>
</param>
<param>
@@ -540,15 +830,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain13</key>
<value>0</value>
</param>
<param>
- <key>ant13</key>
+ <key>ant14</key>
<value></value>
</param>
<param>
- <key>bw13</key>
+ <key>bw14</key>
<value>0</value>
</param>
<param>
@@ -556,15 +850,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain14</key>
<value>0</value>
</param>
<param>
- <key>ant14</key>
+ <key>ant15</key>
<value></value>
</param>
<param>
- <key>bw14</key>
+ <key>bw15</key>
<value>0</value>
</param>
<param>
@@ -572,15 +870,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain15</key>
<value>0</value>
</param>
<param>
- <key>ant15</key>
+ <key>ant16</key>
<value></value>
</param>
<param>
- <key>bw15</key>
+ <key>bw16</key>
<value>0</value>
</param>
<param>
@@ -588,15 +890,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain16</key>
<value>0</value>
</param>
<param>
- <key>ant16</key>
+ <key>ant17</key>
<value></value>
</param>
<param>
- <key>bw16</key>
+ <key>bw17</key>
<value>0</value>
</param>
<param>
@@ -604,15 +910,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain17</key>
<value>0</value>
</param>
<param>
- <key>ant17</key>
+ <key>ant18</key>
<value></value>
</param>
<param>
- <key>bw17</key>
+ <key>bw18</key>
<value>0</value>
</param>
<param>
@@ -620,15 +930,19 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain18</key>
<value>0</value>
</param>
<param>
- <key>ant18</key>
+ <key>ant19</key>
<value></value>
</param>
<param>
- <key>bw18</key>
+ <key>bw19</key>
<value>0</value>
</param>
<param>
@@ -636,23 +950,31 @@
<value>0</value>
</param>
<param>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain19</key>
<value>0</value>
</param>
<param>
- <key>ant19</key>
+ <key>ant1</key>
<value></value>
</param>
<param>
- <key>bw19</key>
+ <key>bw1</key>
<value>0</value>
</param>
<param>
- <key>center_freq20</key>
+ <key>center_freq1</key>
<value>0</value>
</param>
<param>
- <key>gain20</key>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain1</key>
<value>0</value>
</param>
<param>
@@ -664,11 +986,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq21</key>
+ <key>center_freq20</key>
<value>0</value>
</param>
<param>
- <key>gain21</key>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain20</key>
<value>0</value>
</param>
<param>
@@ -680,11 +1006,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq22</key>
+ <key>center_freq21</key>
<value>0</value>
</param>
<param>
- <key>gain22</key>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain21</key>
<value>0</value>
</param>
<param>
@@ -696,11 +1026,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq23</key>
+ <key>center_freq22</key>
<value>0</value>
</param>
<param>
- <key>gain23</key>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain22</key>
<value>0</value>
</param>
<param>
@@ -712,11 +1046,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq24</key>
+ <key>center_freq23</key>
<value>0</value>
</param>
<param>
- <key>gain24</key>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain23</key>
<value>0</value>
</param>
<param>
@@ -728,11 +1066,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq25</key>
+ <key>center_freq24</key>
<value>0</value>
</param>
<param>
- <key>gain25</key>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain24</key>
<value>0</value>
</param>
<param>
@@ -744,11 +1086,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq26</key>
+ <key>center_freq25</key>
<value>0</value>
</param>
<param>
- <key>gain26</key>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain25</key>
<value>0</value>
</param>
<param>
@@ -760,11 +1106,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq27</key>
+ <key>center_freq26</key>
<value>0</value>
</param>
<param>
- <key>gain27</key>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain26</key>
<value>0</value>
</param>
<param>
@@ -776,11 +1126,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq28</key>
+ <key>center_freq27</key>
<value>0</value>
</param>
<param>
- <key>gain28</key>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain27</key>
<value>0</value>
</param>
<param>
@@ -792,11 +1146,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq29</key>
+ <key>center_freq28</key>
<value>0</value>
</param>
<param>
- <key>gain29</key>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain28</key>
<value>0</value>
</param>
<param>
@@ -808,11 +1166,35 @@
<value>0</value>
</param>
<param>
- <key>center_freq30</key>
+ <key>center_freq29</key>
<value>0</value>
</param>
<param>
- <key>gain30</key>
+ <key>norm_gain29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain2</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain2</key>
<value>0</value>
</param>
<param>
@@ -824,11 +1206,15 @@
<value>0</value>
</param>
<param>
- <key>center_freq31</key>
+ <key>center_freq30</key>
<value>0</value>
</param>
<param>
- <key>gain31</key>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain30</key>
<value>0</value>
</param>
<param>
@@ -840,258 +1226,291 @@
<value>0</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>center_freq31</key>
+ <value>0</value>
</param>
<param>
- <key>affinity</key>
+ <key>norm_gain31</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant3</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
+ <key>bw3</key>
<value>0</value>
</param>
<param>
- <key>maxoutbuf</key>
+ <key>center_freq3</key>
<value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(336, 8)</value>
+ <key>norm_gain3</key>
+ <value>False</value>
</param>
<param>
- <key>_rotation</key>
+ <key>gain3</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>qtgui_freq_sink_x</key>
<param>
- <key>id</key>
- <value>qtgui_freq_sink_x_0</value>
+ <key>ant4</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>bw4</key>
+ <value>0</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>center_freq4</key>
+ <value>0</value>
</param>
<param>
- <key>name</key>
- <value>QT GUI Plot</value>
+ <key>norm_gain4</key>
+ <value>False</value>
</param>
<param>
- <key>fftsize</key>
- <value>1024</value>
+ <key>gain4</key>
+ <value>0</value>
</param>
<param>
- <key>wintype</key>
- <value>firdes.WIN_BLACKMAN_hARRIS</value>
+ <key>ant5</key>
+ <value></value>
</param>
<param>
- <key>fc</key>
- <value>initial_fc</value>
+ <key>bw5</key>
+ <value>0</value>
</param>
<param>
- <key>bw</key>
- <value>samp_rate</value>
+ <key>center_freq5</key>
+ <value>0</value>
</param>
<param>
- <key>autoscale</key>
+ <key>norm_gain5</key>
<value>False</value>
</param>
<param>
- <key>average</key>
- <value>1.0</value>
+ <key>gain5</key>
+ <value>0</value>
</param>
<param>
- <key>ymin</key>
- <value>-140</value>
+ <key>ant6</key>
+ <value></value>
</param>
<param>
- <key>ymax</key>
- <value>10</value>
+ <key>bw6</key>
+ <value>0</value>
</param>
<param>
- <key>nconnections</key>
- <value>1</value>
+ <key>center_freq6</key>
+ <value>0</value>
</param>
<param>
- <key>update_time</key>
- <value>0.10</value>
+ <key>norm_gain6</key>
+ <value>False</value>
</param>
<param>
- <key>gui_hint</key>
- <value></value>
+ <key>gain6</key>
+ <value>0</value>
</param>
<param>
- <key>label1</key>
+ <key>ant7</key>
<value></value>
</param>
<param>
- <key>width1</key>
- <value>1</value>
+ <key>bw7</key>
+ <value>0</value>
</param>
<param>
- <key>color1</key>
- <value>"blue"</value>
+ <key>center_freq7</key>
+ <value>0</value>
</param>
<param>
- <key>alpha1</key>
- <value>1.0</value>
+ <key>norm_gain7</key>
+ <value>False</value>
</param>
<param>
- <key>label2</key>
+ <key>gain7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant8</key>
<value></value>
</param>
<param>
- <key>width2</key>
- <value>1</value>
+ <key>bw8</key>
+ <value>0</value>
</param>
<param>
- <key>color2</key>
- <value>"red"</value>
+ <key>center_freq8</key>
+ <value>0</value>
</param>
<param>
- <key>alpha2</key>
- <value>1.0</value>
+ <key>norm_gain8</key>
+ <value>False</value>
</param>
<param>
- <key>label3</key>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant9</key>
<value></value>
</param>
<param>
- <key>width3</key>
- <value>1</value>
+ <key>bw9</key>
+ <value>0</value>
</param>
<param>
- <key>color3</key>
- <value>"green"</value>
+ <key>center_freq9</key>
+ <value>0</value>
</param>
<param>
- <key>alpha3</key>
- <value>1.0</value>
+ <key>norm_gain9</key>
+ <value>False</value>
</param>
<param>
- <key>label4</key>
+ <key>gain9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>clock_rate</key>
+ <value>0.0</value>
+ </param>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>width4</key>
- <value>1</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>color4</key>
- <value>"black"</value>
+ <key>dev_addr</key>
+ <value>""</value>
</param>
<param>
- <key>alpha4</key>
- <value>1.0</value>
+ <key>dev_args</key>
+ <value>""</value>
</param>
<param>
- <key>label5</key>
- <value></value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>width5</key>
- <value>1</value>
+ <key>_coordinate</key>
+ <value>(488, 27)</value>
</param>
<param>
- <key>color5</key>
- <value>"cyan"</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>alpha5</key>
- <value>1.0</value>
+ <key>id</key>
+ <value>uhd_usrp_source_0</value>
</param>
<param>
- <key>label6</key>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
<value></value>
</param>
<param>
- <key>width6</key>
- <value>1</value>
+ <key>sd_spec0</key>
+ <value></value>
</param>
<param>
- <key>color6</key>
- <value>"magenta"</value>
+ <key>time_source0</key>
+ <value></value>
</param>
<param>
- <key>alpha6</key>
- <value>1.0</value>
+ <key>clock_source1</key>
+ <value></value>
</param>
<param>
- <key>label7</key>
+ <key>sd_spec1</key>
<value></value>
</param>
<param>
- <key>width7</key>
- <value>1</value>
+ <key>time_source1</key>
+ <value></value>
</param>
<param>
- <key>color7</key>
- <value>"yellow"</value>
+ <key>clock_source2</key>
+ <value></value>
</param>
<param>
- <key>alpha7</key>
- <value>1.0</value>
+ <key>sd_spec2</key>
+ <value></value>
</param>
<param>
- <key>label8</key>
+ <key>time_source2</key>
<value></value>
</param>
<param>
- <key>width8</key>
- <value>1</value>
+ <key>clock_source3</key>
+ <value></value>
</param>
<param>
- <key>color8</key>
- <value>"dark red"</value>
+ <key>sd_spec3</key>
+ <value></value>
</param>
<param>
- <key>alpha8</key>
- <value>1.0</value>
+ <key>time_source3</key>
+ <value></value>
</param>
<param>
- <key>label9</key>
+ <key>clock_source4</key>
<value></value>
</param>
<param>
- <key>width9</key>
- <value>1</value>
+ <key>sd_spec4</key>
+ <value></value>
</param>
<param>
- <key>color9</key>
- <value>"dark green"</value>
+ <key>time_source4</key>
+ <value></value>
</param>
<param>
- <key>alpha9</key>
- <value>1.0</value>
+ <key>clock_source5</key>
+ <value></value>
</param>
<param>
- <key>label10</key>
+ <key>sd_spec5</key>
<value></value>
</param>
<param>
- <key>width10</key>
- <value>1</value>
+ <key>time_source5</key>
+ <value></value>
</param>
<param>
- <key>color10</key>
- <value>"dark blue"</value>
+ <key>clock_source6</key>
+ <value></value>
</param>
<param>
- <key>alpha10</key>
- <value>1.0</value>
+ <key>sd_spec6</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
+ <key>time_source6</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
<value></value>
</param>
<param>
@@ -1099,23 +1518,49 @@
<value>0</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>nchan</key>
+ <value>1</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(330, 104)</value>
+ <key>num_mboards</key>
+ <value>1</value>
</param>
<param>
- <key>_rotation</key>
- <value>180</value>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>stream_args</key>
+ <value></value>
+ </param>
+ <param>
+ <key>stream_chans</key>
+ <value>[]</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
</param>
</block>
<connection>
- <source_block_id>uhd_usrp_source_0</source_block_id>
+ <source_block_id>blocks_message_strobe_0</source_block_id>
+ <sink_block_id>uhd_usrp_source_0</sink_block_id>
+ <source_key>strobe</source_key>
+ <sink_key>command</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>qtgui_freq_sink_x_0</source_block_id>
<sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
+ <source_key>freq</source_key>
+ <sink_key>freq</sink_key>
</connection>
<connection>
<source_block_id>qtgui_freq_sink_x_0</source_block_id>
@@ -1124,9 +1569,9 @@
<sink_key>command</sink_key>
</connection>
<connection>
- <source_block_id>qtgui_freq_sink_x_0</source_block_id>
+ <source_block_id>uhd_usrp_source_0</source_block_id>
<sink_block_id>qtgui_freq_sink_x_0</sink_block_id>
- <source_key>freq</source_key>
- <sink_key>freq</sink_key>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
</connection>
</flow_graph>
diff --git a/gr-uhd/examples/python/freq_hopping.py b/gr-uhd/examples/python/freq_hopping.py
index 5da5efa241..ce33a92a51 100755
--- a/gr-uhd/examples/python/freq_hopping.py
+++ b/gr-uhd/examples/python/freq_hopping.py
@@ -24,7 +24,6 @@
TXs a waveform (either from a file, or a sinusoid) in a frequency-hopping manner.
"""
-import time
import numpy
import argparse
import pmt
@@ -35,7 +34,7 @@ from gnuradio import uhd
def setup_parser():
""" Setup the parser for the frequency hopper. """
parser = argparse.ArgumentParser(
- description="Transmit a signal in a frequency-hopping manner, using tx_freq tags."
+ description="Transmit a signal in a frequency-hopping manner, using tx_freq tags."
)
parser.add_argument('-i', '--input-file', type=file, default=None,
help="File with samples to transmit. If left out, will transmit a sinusoid.")
@@ -54,7 +53,9 @@ def setup_parser():
parser.add_argument("-t", "--hop-time", type=float, default=1000,
help="Time between hops in milliseconds. This must be larger than or equal to the burst duration as set by --samp-per-burst")
parser.add_argument("-f", "--freq", type=float, default=2.45e9,
- help="Base frequency. This is the lowest frequency at which the USRP will Tx.")
+ help="Base frequency. This is the middle channel frequency at which the USRP will Tx.")
+ parser.add_argument("--dsp", action='store_true',
+ help="DSP tuning only.")
parser.add_argument("-d", "--freq-delta", type=float, default=1e6,
help="Channel spacing.")
parser.add_argument("-c", "--num-channels", type=int, default=5,
@@ -64,7 +65,7 @@ def setup_parser():
parser.add_argument("-p", "--post-tuning", action='count',
help="Tune after transmitting. Default is to tune immediately before transmitting.")
parser.add_argument("-v", "--verbose", action='count',
- help="Print more information.")
+ help="Print more information. The morer the printier.")
return parser
@@ -73,7 +74,7 @@ class FrequencyHopperSrc(gr.hier_block2):
def __init__(
self,
n_bursts, n_channels,
- freq_delta, base_freq,
+ freq_delta, base_freq, dsp_tuning,
burst_length, base_time, hop_time,
post_tuning=False,
tx_gain=0,
@@ -85,8 +86,10 @@ class FrequencyHopperSrc(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_gr_complex),
)
n_samples_total = n_bursts * burst_length
- self.hop_sequence = numpy.arange(base_freq, base_freq + n_channels * freq_delta, freq_delta)
+ lowest_frequency = base_freq - numpy.floor(n_channels/2) * freq_delta
+ self.hop_sequence = [lowest_frequency + n * freq_delta for n in xrange(n_channels)]
numpy.random.shuffle(self.hop_sequence)
+ # Repeat that:
self.hop_sequence = [self.hop_sequence[x % n_channels] for x in xrange(n_bursts)]
if verbose:
print "Hop Frequencies | Hop Pattern"
@@ -103,20 +106,19 @@ class FrequencyHopperSrc(gr.hier_block2):
gain_tag = gr.tag_t()
gain_tag.offset = 0
gain_tag.key = pmt.string_to_symbol('tx_command')
- gain_tag.value = pmt.cons(
- pmt.intern("gain"),
- # These are both valid:
- #pmt.from_double(tx_gain)
- pmt.cons(pmt.to_pmt(0), pmt.to_pmt(tx_gain))
- )
+ gain_tag.value = pmt.to_pmt({'gain': tx_gain})
tag_list = [gain_tag,]
- for i in xrange(n_bursts):
+ for i in xrange(len(self.hop_sequence)):
tune_tag = gr.tag_t()
tune_tag.offset = i * burst_length
- if i > 0 and post_tuning:
+ if i > 0 and post_tuning and not dsp_tuning: # TODO dsp_tuning should also be able to do post_tuning
tune_tag.offset -= 1 # Move it to last sample of previous burst
- tune_tag.key = pmt.string_to_symbol('tx_freq')
- tune_tag.value = pmt.to_pmt(self.hop_sequence[i])
+ if dsp_tuning:
+ tune_tag.key = pmt.string_to_symbol('tx_command')
+ tune_tag.value = pmt.to_pmt({'lo_freq': base_freq, 'dsp_freq': base_freq - self.hop_sequence[i]})
+ else:
+ tune_tag.key = pmt.string_to_symbol('tx_freq')
+ tune_tag.value = pmt.to_pmt(self.hop_sequence[i])
tag_list.append(tune_tag)
length_tag = gr.tag_t()
length_tag.offset = i * burst_length
@@ -164,7 +166,7 @@ class FlowGraph(gr.top_block):
raise SystemExit, 1
hopper_block = FrequencyHopperSrc(
options.num_bursts, options.num_channels,
- options.freq_delta, options.freq,
+ options.freq_delta, options.freq, options.dsp,
options.samp_per_burst, 1.0, options.hop_time / 1000.,
options.post_tuning,
options.gain,
@@ -202,7 +204,7 @@ def main():
args = setup_parser().parse_args()
if (1.0 * args.samp_per_burst / args.rate) > args.hop_time * 1e-3:
print "Burst duration must be smaller than hop time."
- raise SystemExit, 1
+ exit(1)
if args.verbose:
print_hopper_stats(args)
top_block = FlowGraph(args)
diff --git a/gr-uhd/examples/python/usrp_spectrum_sense.py b/gr-uhd/examples/python/usrp_spectrum_sense.py
index ba45a2e80e..b1ea6b44d8 100755
--- a/gr-uhd/examples/python/usrp_spectrum_sense.py
+++ b/gr-uhd/examples/python/usrp_spectrum_sense.py
@@ -33,6 +33,7 @@ import math
import struct
import threading
from datetime import datetime
+import time
sys.stderr.write("Warning: this may have issues on some machines+Python version combinations to seg fault due to the callback in bin_statitics.\n\n")
@@ -271,6 +272,8 @@ def main_loop(tb):
bin_start = int(tb.fft_size * ((1 - 0.75) / 2))
bin_stop = int(tb.fft_size - bin_start)
+ timestamp = 0
+ centerfreq = 0
while 1:
# Get the next message sent from the C++ code (blocking call).
@@ -282,6 +285,15 @@ def main_loop(tb):
# m.raw_data is a string that contains the binary floats.
# You could write this as binary to a file.
+ # Scanning rate
+ if timestamp == 0:
+ timestamp = time.time()
+ centerfreq = m.center_freq
+ if m.center_freq < centerfreq:
+ sys.stderr.write("scanned %.1fMHz in %.1fs\n" % ((centerfreq - m.center_freq)/1.0e6, time.time() - timestamp))
+ timestamp = time.time()
+ centerfreq = m.center_freq
+
for i_bin in range(bin_start, bin_stop):
center_freq = m.center_freq
diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py
index fda1b9dfd7..72f1b50135 100644
--- a/gr-uhd/grc/gen_uhd_usrp_blocks.py
+++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py
@@ -23,7 +23,7 @@ MAIN_TMPL = """\
<block>
<name>UHD: USRP $sourk.title()</name>
<key>uhd_usrp_$(sourk)</key>
- <throttle>1</throttle>
+ <flags>throttle</flags>
<import>from gnuradio import uhd</import>
<import>import time</import>
<make>uhd.usrp_$(sourk)(
diff --git a/gr-uhd/include/gnuradio/uhd/CMakeLists.txt b/gr-uhd/include/gnuradio/uhd/CMakeLists.txt
index 71c17b89cd..b1f3345d78 100644
--- a/gr-uhd/include/gnuradio/uhd/CMakeLists.txt
+++ b/gr-uhd/include/gnuradio/uhd/CMakeLists.txt
@@ -22,6 +22,7 @@
########################################################################
install(FILES
api.h
+ usrp_block.h
usrp_source.h
usrp_sink.h
amsg_source.h
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_block.h b/gr-uhd/include/gnuradio/uhd/usrp_block.h
new file mode 100644
index 0000000000..d57e1d24cb
--- /dev/null
+++ b/gr-uhd/include/gnuradio/uhd/usrp_block.h
@@ -0,0 +1,564 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_UHD_USRP_BLOCK_H
+#define INCLUDED_GR_UHD_USRP_BLOCK_H
+
+#include <gnuradio/uhd/api.h>
+#include <gnuradio/sync_block.h>
+#include <uhd/usrp/multi_usrp.hpp>
+
+namespace gr {
+ namespace uhd {
+
+ /*! Base class for USRP blocks.
+ * \ingroup uhd_blk
+ *
+ * Note that many of the functions defined here differ between
+ * Rx and Tx configurations. As an example, set_center_freq()
+ * will set the Rx frequency for a usrp_source object, and the
+ * Tx frequency on a usrp_sink object.
+ */
+ class GR_UHD_API usrp_block : public gr::sync_block
+ {
+ protected:
+ usrp_block() {}; // For virtual sub-classing
+ usrp_block(const std::string &name,
+ gr::io_signature::sptr input_signature,
+ gr::io_signature::sptr output_signature);
+ public:
+
+ /*!
+ * Set the frontend specification.
+ *
+ * \param spec the subdev spec markup string
+ * \param mboard the motherboard index 0 to M-1
+ */
+ virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0;
+
+ /*!
+ * Get the frontend specification.
+ *
+ * \param mboard the motherboard index 0 to M-1
+ * \return the frontend specification in use
+ */
+ virtual std::string get_subdev_spec(size_t mboard = 0) = 0;
+
+ /*!
+ * Set the sample rate for this connection to the USRP.
+ *
+ * \param rate a new rate in Sps
+ */
+ virtual void set_samp_rate(double rate) = 0;
+
+ /*!
+ * Get the sample rate for this connection to the USRP.
+ * This is the actual sample rate and may differ from the rate set.
+ *
+ * \return the actual rate in Sps
+ */
+ virtual double get_samp_rate(void) = 0;
+
+ /*!
+ * Get the possible sample rates for this connection.
+ *
+ * \return a range of rates in Sps
+ */
+ virtual ::uhd::meta_range_t get_samp_rates(void) = 0;
+
+ /*!
+ * Tune the selected channel to the desired center frequency.
+ *
+ * \param tune_request the tune request instructions
+ * \param chan the channel index 0 to N-1
+ * \return a tune result with the actual frequencies
+ */
+ virtual ::uhd::tune_result_t set_center_freq(
+ const ::uhd::tune_request_t tune_request,
+ size_t chan = 0
+ ) = 0;
+
+ /*!
+ * Tune the the selected channel to the desired center frequency.
+ *
+ * This is a wrapper around set_center_freq() so that in this case,
+ * the user can pass a single frequency in the call instead of
+ * having to generate a tune_request_t object.
+ *
+ * \param freq the desired frequency in Hz
+ * \param chan the channel index 0 to N-1
+ * \return a tune result with the actual frequencies
+ */
+ ::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
+ {
+ return set_center_freq(::uhd::tune_request_t(freq), chan);
+ }
+
+ /*!
+ * Get the center frequency.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the frequency in Hz
+ */
+ virtual double get_center_freq(size_t chan = 0) = 0;
+
+ /*!
+ * Get the tunable frequency range.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the frequency range in Hz
+ */
+ virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
+
+ /*!
+ * Set the gain for the selected channel.
+ *
+ * \param gain the gain in dB
+ * \param chan the channel index 0 to N-1
+ */
+ virtual void set_gain(double gain, size_t chan = 0) = 0;
+
+ /*!
+ * Set the named gain on the dboard.
+ *
+ * \param gain the gain in dB
+ * \param name the name of the gain stage
+ * \param chan the channel index 0 to N-1
+ */
+ virtual void set_gain(double gain,
+ const std::string &name,
+ size_t chan = 0) = 0;
+
+ /*!
+ * Set the normalized gain.
+ *
+ * The normalized gain is always in [0, 1], regardless of the device.
+ * 0 corresponds to minimum gain (usually 0 dB, but make sure to read the device
+ * notes in the UHD manual) and 1 corresponds to maximum gain.
+ * This will work for any UHD device. Use get_gain() to see which dB value
+ * the normalized gain value corresponds to.
+ *
+ * Note that it is not possible to specify a gain name for this function.
+ *
+ * \throws A runtime_error if \p norm_gain is not within the valid range.
+ *
+ * \param norm_gain the gain in fractions of the gain range (must be 0 <= norm_gain <= 1)
+ * \param chan the channel index 0 to N-1
+ */
+ virtual void set_normalized_gain(double norm_gain, size_t chan = 0) = 0;
+
+ /*!
+ * Get the actual dboard gain setting.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the actual gain in dB
+ */
+ virtual double get_gain(size_t chan = 0) = 0;
+
+ /*!
+ * Get the actual dboard gain setting of named stage.
+ *
+ * \param name the name of the gain stage
+ * \param chan the channel index 0 to N-1
+ * \return the actual gain in dB
+ */
+ virtual double get_gain(const std::string &name,
+ size_t chan = 0) = 0;
+
+ /*!
+ * Returns the normalized gain.
+ *
+ * The normalized gain is always in [0, 1], regardless of the device.
+ * See also set_normalized_gain().
+ *
+ * Note that it is not possible to specify a gain name for
+ * this function, the result is over the entire gain chain.
+ *
+ * \param chan the channel index 0 to N-1
+ */
+ virtual double get_normalized_gain(size_t chan = 0) = 0;
+
+ /*!
+ * Get the actual dboard gain setting of named stage.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the actual gain in dB
+ */
+ virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
+
+ /*!
+ * Get the settable gain range.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the gain range in dB
+ */
+ virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
+
+ /*!
+ * Get the settable gain range.
+ *
+ * \param name the name of the gain stage
+ * \param chan the channel index 0 to N-1
+ * \return the gain range in dB
+ */
+ virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
+ size_t chan = 0) = 0;
+
+ /*!
+ * Set the antenna to use for a given channel.
+ *
+ * \param ant the antenna string
+ * \param chan the channel index 0 to N-1
+ */
+ virtual void set_antenna(const std::string &ant,
+ size_t chan = 0) = 0;
+
+ /*!
+ * Get the antenna in use.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the antenna string
+ */
+ virtual std::string get_antenna(size_t chan = 0) = 0;
+
+ /*!
+ * Get a list of possible antennas on a given channel.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return a vector of antenna strings
+ */
+ virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
+
+ /*!
+ * 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 the bandpass filter setting on the RF frontend.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return bandwidth of the filter in Hz
+ */
+ virtual double get_bandwidth(size_t chan = 0) = 0;
+
+ /*!
+ * Get the bandpass filter range of the RF frontend.
+ *
+ * \param chan the channel index 0 to N-1
+ * \return the range of the filter bandwidth in Hz
+ */
+ virtual ::uhd::freq_range_t get_bandwidth_range(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_sensor(const std::string &name,
+ size_t chan = 0) = 0;
+
+ /*!
+ * 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_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.
+ *
+ * \param name the name of the sensor
+ * \param mboard the motherboard index 0 to M-1
+ * \return a sensor value object
+ */
+ virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
+ size_t mboard = 0) = 0;
+
+ /*!
+ * Get a list of possible motherboard sensor names.
+ *
+ * \param mboard the motherboard index 0 to M-1
+ * \return a vector of sensor names
+ */
+ virtual std::vector<std::string> get_mboard_sensor_names(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
+ */
+ virtual double get_clock_rate(size_t mboard = 0) = 0;
+
+ /*!
+ * Set the master clock rate.
+ *
+ * \param rate the new rate in Hz
+ * \param mboard the motherboard index 0 to M-1
+ */
+ virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
+
+ /*!
+ * Get the current time registers.
+ *
+ * \param mboard the motherboard index 0 to M-1
+ * \return the current usrp time
+ */
+ virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
+
+ /*!
+ * Get the time when the last pps pulse occured.
+ * \param mboard the motherboard index 0 to M-1
+ * \return the current usrp time
+ */
+ virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
+
+ /*!
+ * Sets the time registers immediately.
+ * \param time_spec the new time
+ * \param mboard the motherboard index 0 to M-1
+ */
+ virtual void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard = 0) = 0;
+
+ /*!
+ * Set the time registers at the next pps.
+ * \param time_spec the new time
+ */
+ virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
+
+ /*!
+ * Sync the time registers with an unknown pps edge.
+ * \param time_spec the new time
+ */
+ 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
+ */
+ virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0;
+
+ /*!
+ * Get access to the underlying uhd device object.
+ *
+ * NOTE: This function is only available in C++.
+ * \return the multi usrp device object
+ */
+ virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
+
+ /*!
+ * Perform write on the user configuration register bus. These
+ * only exist if the user has implemented custom setting
+ * registers in the device FPGA.
+ *
+ * \param addr 8-bit register address
+ * \param data 32-bit register value
+ * \param mboard which motherboard to set the user register
+ */
+ virtual void set_user_register(const uint8_t addr,
+ const uint32_t data,
+ size_t mboard = 0) = 0;
+
+ /*!
+ * 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;
+
+ /*!
+ * Update the stream args for this device.
+ *
+ * This update will only take effect after a restart of the
+ * streaming, or before streaming and after construction.
+ * This will also delete the current streamer.
+ * Note you cannot change the I/O signature of this block using
+ * this function, or it will throw.
+ *
+ * It is possible to leave the 'channels' fields of \p stream_args
+ * unset. In this case, the previous channels field is used.
+ *
+ * \param stream_args New stream args.
+ * \throws std::runtime_error if new settings are invalid.
+ */
+ virtual void set_stream_args(const ::uhd::stream_args_t &stream_args) = 0;
+
+ /*******************************************************************
+ * GPIO methods
+ ******************************************************************/
+ /*!
+ * Enumerate GPIO banks on the current device.
+ * \param mboard the motherboard index 0 to M-1
+ * \return a list of string for each bank name
+ */
+ virtual std::vector<std::string> get_gpio_banks(const size_t mboard) = 0;
+
+ /*!
+ * Set a GPIO attribute on a particular GPIO bank.
+ * Possible attribute names:
+ * - CTRL - 1 for ATR mode 0 for GPIO mode
+ * - DDR - 1 for output 0 for input
+ * - OUT - GPIO output level (not ATR mode)
+ * - ATR_0X - ATR idle state
+ * - ATR_RX - ATR receive only state
+ * - ATR_TX - ATR transmit only state
+ * - ATR_XX - ATR full duplex state
+ * \param bank the name of a GPIO bank
+ * \param attr the name of a GPIO attribute
+ * \param value the new value for this GPIO bank
+ * \param mask the bit mask to effect which pins are changed
+ * \param mboard the motherboard index 0 to M-1
+ */
+ virtual void set_gpio_attr(
+ const std::string &bank,
+ const std::string &attr,
+ const boost::uint32_t value,
+ const boost::uint32_t mask = 0xffffffff,
+ const size_t mboard = 0
+ ) = 0;
+
+ /*!
+ * Get a GPIO attribute on a particular GPIO bank.
+ * Possible attribute names:
+ * - CTRL - 1 for ATR mode 0 for GPIO mode
+ * - DDR - 1 for output 0 for input
+ * - OUT - GPIO output level (not ATR mode)
+ * - ATR_0X - ATR idle state
+ * - ATR_RX - ATR receive only state
+ * - ATR_TX - ATR transmit only state
+ * - ATR_XX - ATR full duplex state
+ * - READBACK - readback input GPIOs
+ * \param bank the name of a GPIO bank
+ * \param attr the name of a GPIO attribute
+ * \param mboard the motherboard index 0 to M-1
+ * \return the value set for this attribute
+ */
+ virtual boost::uint32_t get_gpio_attr(
+ const std::string &bank,
+ const std::string &attr,
+ const size_t mboard = 0
+ ) = 0;
+
+ };
+
+ } /* namespace uhd */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_UHD_USRP_BLOCK_H */
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_sink.h b/gr-uhd/include/gnuradio/uhd/usrp_sink.h
index dd1bd6a73a..4ccb83f595 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_sink.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_sink.h
@@ -23,9 +23,7 @@
#ifndef INCLUDED_GR_UHD_USRP_SINK_H
#define INCLUDED_GR_UHD_USRP_SINK_H
-#include <gnuradio/uhd/api.h>
-#include <gnuradio/sync_block.h>
-#include <uhd/usrp/multi_usrp.hpp>
+#include <gnuradio/uhd/usrp_block.h>
// TODO In 3.8, UHD 3.4 will be required and we can remove all these ifdefs
#ifndef INCLUDED_UHD_STREAM_HPP
@@ -54,7 +52,72 @@ namespace gr {
class uhd_usrp_sink;
- class GR_UHD_API usrp_sink : virtual public sync_block
+ /*! USRP Sink -- Radio Transmitter
+ * \ingroup uhd_blk
+ *
+ *
+ * The USRP sink block reads a stream and transmits the samples.
+ * The sink block also provides API calls for transmitter settings.
+ * See also gr::uhd::usrp_block for more public API calls.
+ *
+ * \section uhd_tx_tagging TX Stream tagging
+ *
+ * The following tag keys will be consumed by the work function:
+ * - pmt::string_to_symbol("tx_sob")
+ * - pmt::string_to_symbol("tx_eob")
+ * - pmt::string_to_symbol("tx_time")
+ * - pmt::string_to_symbol("tx_freq")
+ * - pmt::string_to_symbol("tx_command")
+ * - pmt::string_to_symbol(tsb_tag_name)
+ *
+ * Any other tag will be ignored.
+ *
+ * \section uhd_tx_burstys Bursty Transmission
+ *
+ * There are multiple ways to do bursty transmission without triggering
+ * underruns:
+ * - Using SOB/EOB tags
+ * - Using tagged streams (See \ref page_tagged_stream_blocks)
+ *
+ * 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).
+ *
+ * If `tsb_tag_name` is not an empty string, all "tx_sob" and "tx_eob"
+ * tags will be ignored, and the input is assumed to a tagged stream.
+ *
+ * If sob/eob tags or length tags are used, this block understands that
+ * the data is bursty, and will configure the USRP to make sure there's
+ * no underruns after transmitting the final sample of a burst.
+ *
+ * \section uhd_tx_time Timestamps
+ *
+ * The timestamp tag value is a PMT tuple of the following:
+ * (uint64 seconds, double fractional seconds).
+ *
+ * The tx_freq tag has to be a double or a pair of form (channel, frequency),
+ * with frequency being a double and channel being an integer.
+ * This tag will trigger a tune command to the USRP
+ * to the given frequency, if possible. Note that oscillators need some time
+ * to stabilize after this! Don't expect clean data to be sent immediately after this command.
+ * If channel is omitted, and only a double is given, it will set this frequency to all
+ * channels.
+ *
+ * The command tag can carry a PMT command. See the following section.
+ *
+ * \section uhd_tx_commands Command interface
+ *
+ * There are two ways of passing commands to this block:
+ * 1. tx_command tag. The command is attached to a sample, and will executed
+ * before the sample is transmitted, and after the previous sample.
+ * 2. The 'command' message port. The command is executed asynchronously,
+ * as soon as possible.
+ *
+ * In both cases, the payload of the command is a PMT command, as described
+ * in Section \ref uhd_command_syntax.
+ *
+ * For a more general description of the gr-uhd components, see \ref page_uhd.
+ */
+ class GR_UHD_API usrp_sink : virtual public usrp_block
{
public:
// gr::uhd::usrp_sink::sptr
@@ -68,64 +131,10 @@ namespace gr {
* gr::uhd::usrp_sink::make(const ::uhd::device_addr_t, const ::uhd::stream_args_t, const std::string).
*/
static sptr make(const ::uhd::device_addr_t &device_addr,
- const ::uhd::io_type_t &io_type,
- size_t num_channels);
+ const ::uhd::io_type_t &io_type,
+ size_t num_channels);
/*!
- * \brief Make a new USRP sink block (usually a radio transmitter).
- *
- * The USRP sink block reads a stream and transmits the samples.
- * The sink block also provides API calls for transmitter settings.
- *
- * \section uhd_tx_tagging TX Stream tagging
- *
- * The following tag keys will be consumed by the work function:
- * - pmt::string_to_symbol("tx_sob")
- * - pmt::string_to_symbol("tx_eob")
- * - pmt::string_to_symbol("tx_time")
- * - pmt::string_to_symbol("tx_freq")
- * - pmt::string_to_symbol("tx_command")
- * - pmt::string_to_symbol(tsb_tag_name)
- *
- * Any other tag will be ignored.
- *
- * 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).
- *
- * If `tsb_tag_name` is not an empty string, all "tx_sob" and "tx_eob"
- * tags will be ignored, and the input is assumed to a tagged stream,
- * as described in \ref page_tagged_stream_blocks.
- *
- * If sob/eob tags or length tags are used, this block understands that
- * the data is bursty, and will configure the USRP to make sure there's
- * no underruns after transmitting the final sample of a burst.
- *
- * The timestamp tag value is a PMT tuple of the following:
- * (uint64 seconds, double fractional seconds).
- *
- * The tx_freq tag has to be a double or a pair of form (channel, frequency),
- * with frequency being a double and channel being an integer.
- * This tag will trigger a tune command to the USRP
- * to the given frequency, if possible. Note that oscillators need some time
- * to stabilize after this! Don't expect clean data to be sent immediately after this command.
- * If channel is omitted, and only a double is given, it will set this frequency to all
- * channels.
- *
- * The command tag can carry a PMT command. See the following section.
- *
- * \section uhd_tx_commands Command interface
- *
- * There are two ways of passing commands to this block:
- * 1. tx_command tag. The command is attached to a sample, and will executed
- * before the sample is transmitted, and after the previous sample.
- * 2. The 'command' message port. The command is executed asynchronously,
- * as soon as possible.
- *
- * In both cases, the payload of the command is a PMT command, as described
- * in Section \ref uhd_command_syntax.
- *
- * For a more general description of the gr-uhd components, see \ref page_uhd.
- *
* \param device_addr the address to identify the hardware
* \param stream_args the IO format and channel specification
* \param tsb_tag_name the name of the tag identifying tagged stream length
@@ -158,205 +167,6 @@ namespace gr {
virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan = 0) = 0;
/*!
- * Set the frontend specification.
- * \param spec the subdev spec markup string
- * \param mboard the motherboard index 0 to M-1
- */
- virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0;
-
- /*!
- * Get the TX frontend specification.
- * \param mboard the motherboard index 0 to M-1
- * \return the frontend specification in use
- */
- virtual std::string get_subdev_spec (size_t mboard = 0) = 0;
-
- /*!
- * Set the sample rate for the usrp device.
- * \param rate a new rate in Sps
- */
- virtual void set_samp_rate(double rate) = 0;
-
- /*!
- * Get the sample rate for the usrp device.
- * This is the actual sample rate and may differ from the rate set.
- * \return the actual rate in Sps
- */
- 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
- * \return a tune result with the actual frequencies
- */
- virtual ::uhd::tune_result_t set_center_freq
- (const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
-
- /*!
- * Tune the usrp device to the desired center frequency.
- * This is a wrapper around set center freq so that in this case,
- * the user can pass a single frequency in the call through swig.
- * \param freq the desired frequency in Hz
- * \param chan the channel index 0 to N-1
- * \return a tune result with the actual frequencies
- */
- ::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
- {
- return set_center_freq(::uhd::tune_request_t(freq), chan);
- }
-
- /*!
- * Get the center frequency.
- * \param chan the channel index 0 to N-1
- * \return the frequency in Hz
- */
- virtual double get_center_freq(size_t chan = 0) = 0;
-
- /*!
- * Get the tunable frequency range.
- * \param chan the channel index 0 to N-1
- * \return the frequency range in Hz
- */
- virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
-
- /*!
- * Set the gain for the dboard.
- * \param gain the gain in dB
- * \param chan the channel index 0 to N-1
- */
- virtual void set_gain(double gain, size_t chan = 0) = 0;
-
- /*!
- * Set the named gain on the dboard.
- * \param gain the gain in dB
- * \param name the name of the gain stage
- * \param chan the channel index 0 to N-1
- */
- virtual void set_gain(double gain,
- const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * Set the normalized gain.
- *
- * The normalized gain is always in [0, 1], regardless of the device.
- * 0 corresponds to minimum gain (usually 0 dB, but make sure to read the device
- * notes in the UHD manual) and 1 corresponds to maximum gain.
- * This will work for any UHD device. Use get_gain() to see which dB value
- * the normalized gain value corresponds to.
- *
- * Note that it is not possible to specify a gain name for this function.
- *
- * \throws A runtime_error if \p norm_gain is not within the valid range.
- *
- * \param norm_gain the gain in fractions of the gain range (must be 0 <= norm_gain <= 1)
- * \param chan the channel index 0 to N-1
- */
- virtual void set_normalized_gain(double norm_gain, size_t chan = 0) = 0;
-
- /*!
- * Get the actual dboard gain setting.
- * \param chan the channel index 0 to N-1
- * \return the actual gain in dB
- */
- virtual double get_gain(size_t chan = 0) = 0;
-
- /*!
- * Get the actual dboard gain setting of named stage.
- * \param name the name of the gain stage
- * \param chan the channel index 0 to N-1
- * \return the actual gain in dB
- */
- virtual double get_gain(const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * Returns the normalized gain.
- *
- * The normalized gain is always in [0, 1], regardless of the device.
- * See also set_normalized_gain().
- *
- * Note that it is not possible to specify a gain name for this function,
- * the result is over the entire gain chain.
- *
- * \param chan the channel index 0 to N-1
- */
- virtual double get_normalized_gain(size_t chan = 0) = 0;
-
- /*!
- * Get the actual dboard gain setting of named stage.
- * \param chan the channel index 0 to N-1
- * \return the actual gain in dB
- */
- virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
-
- /*!
- * Get the settable gain range.
- * \param chan the channel index 0 to N-1
- * \return the gain range in dB
- */
- virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
-
- /*!
- * Get the settable gain range.
- * \param name the name of the gain stage
- * \param chan the channel index 0 to N-1
- * \return the gain range in dB
- */
- virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * Set the antenna to use.
- * \param ant the antenna string
- * \param chan the channel index 0 to N-1
- */
- virtual void set_antenna(const std::string &ant,
- size_t chan = 0) = 0;
-
- /*!
- * Get the antenna in use.
- * \param chan the channel index 0 to N-1
- * \return the antenna string
- */
- virtual std::string get_antenna(size_t chan = 0) = 0;
-
- /*!
- * Get a list of possible antennas.
- * \param chan the channel index 0 to N-1
- * \return a vector of antenna strings
- */
- virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
-
- /*!
- * 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 the bandpass filter setting on the RF frontend.
- * \param chan the channel index 0 to N-1
- * \return bandwidth of the filter in Hz
- */
- virtual double get_bandwidth(size_t chan = 0) = 0;
-
- /*!
- * Get the bandpass filter range of the RF frontend.
- * \param chan the channel index 0 to N-1
- * \return the range of the filter bandwidth in Hz
- */
- virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
-
- /*!
* 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)
@@ -375,218 +185,6 @@ namespace gr {
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_sensor(const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * 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_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.
- * \param name the name of the sensor
- * \param mboard the motherboard index 0 to M-1
- * \return a sensor value object
- */
- virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
- size_t mboard = 0) = 0;
-
- /*!
- * Get a list of possible motherboard sensor names.
- * \param mboard the motherboard index 0 to M-1
- * \return a vector of sensor names
- */
- virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0;
-
- /*!
- * 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
- */
- virtual double get_clock_rate(size_t mboard = 0) = 0;
-
- /*!
- * Set the master clock rate.
- * \param rate the new rate in Hz
- * \param mboard the motherboard index 0 to M-1
- */
- virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
-
- /*!
- * Get the current time registers.
- * \param mboard the motherboard index 0 to M-1
- * \return the current usrp time
- */
- virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
-
- /*!
- * Get the time when the last pps pulse occured.
- * \param mboard the motherboard index 0 to M-1
- * \return the current usrp time
- */
- virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
-
- /*!
- * Sets the time registers immediately.
- * \param time_spec the new time
- * \param mboard the motherboard index 0 to M-1
- */
- virtual void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard = 0) = 0;
-
- /*!
- * Set the time registers at the next pps.
- * \param time_spec the new time
- */
- virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
-
- /*!
- * Sync the time registers with an unknown pps edge.
- * \param time_spec the new time
- */
- 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
- */
- virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0;
-
- /*!
- * Get access to the underlying uhd device object.
- *
- * NOTE: This function is only available in C++.
- * \return the multi usrp device object
- */
- virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
-
- /*!
- * Perform write on the user configuration register bus. These
- * only exist if the user has implemented custom setting
- * registers in the device FPGA.
- * \param addr 8-bit register address
- * \param data 32-bit register value
- * \param mboard which motherboard to set the user register
- */
- virtual void set_user_register(const uint8_t addr,
- const uint32_t data,
- size_t mboard = 0) = 0;
-
- /*!
- * Update the stream args for this device.
- *
- * This update will only take effect after a restart of the
- * streaming, or before streaming and after construction.
- * This will also delete the current streamer.
- * Note you cannot change the I/O signature of this block using
- * this function, or it will throw.
- *
- * It is possible to leave the 'channels' fields of \p stream_args
- * unset. In this case, the previous channels field is used.
- *
- * \param stream_args New stream args.
- * \throws std::runtime_error if new settings are invalid.
- */
- virtual void set_stream_args(const ::uhd::stream_args_t &stream_args) = 0;
};
} /* namespace uhd */
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_source.h b/gr-uhd/include/gnuradio/uhd/usrp_source.h
index 7da39683d1..19b3feb61f 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_source.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_source.h
@@ -23,11 +23,9 @@
#ifndef INCLUDED_GR_UHD_USRP_SOURCE_H
#define INCLUDED_GR_UHD_USRP_SOURCE_H
-#include <gnuradio/uhd/api.h>
-#include <gnuradio/sync_block.h>
-#include <uhd/usrp/multi_usrp.hpp>
+#include <gnuradio/uhd/usrp_block.h>
-// TODO In 3.8, UHD 3.4 will be required and we can remove all these ifdefs
+// TODO In 3.8, UHD 3.6 will be required and we can remove all these ifdefs
#ifndef INCLUDED_UHD_STREAM_HPP
namespace uhd {
struct GR_UHD_API stream_args_t
@@ -54,7 +52,31 @@ namespace gr {
class uhd_usrp_source;
- class GR_UHD_API usrp_source : virtual public sync_block
+ /*! USRP Source -- Radio Receiver
+ * \ingroup uhd_blk
+ *
+ * The USRP source block receives samples and writes to a stream.
+ * The source block also provides API calls for receiver settings.
+ * See also gr::uhd::usrp_block for more public API calls.
+ *
+ * RX Stream tagging:
+ *
+ * The following tag keys will be produced by the work function:
+ * - pmt::string_to_symbol("rx_time")
+ *
+ * The timestamp 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.
+ *
+ * \section uhd_rx_command_iface Command interface
+ *
+ * This block has a message port, which consumes UHD PMT commands.
+ * For a description of the command syntax, see Section \ref uhd_command_syntax.
+ *
+ * For a more general description of the gr-uhd components, see \ref page_uhd.
+ *
+ */
+ class GR_UHD_API usrp_source : virtual public usrp_block
{
public:
// gr::uhd::usrp_source::sptr
@@ -72,27 +94,6 @@ namespace gr {
size_t num_channels);
/*!
- * \brief Make a new USRP source block (usually a radio receiver).
- *
- * 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::string_to_symbol("rx_time")
- *
- * The timestamp 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.
- *
- * \section uhd_rx_command_iface Command interface
- *
- * This block has a message port, which consumes UHD PMT commands.
- * For a description of the command syntax, see Section \ref uhd_command_syntax.
- *
- * For a more general description of the gr-uhd components, see \ref page_uhd.
- *
* \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
@@ -137,205 +138,6 @@ namespace gr {
virtual ::uhd::dict<std::string, std::string> get_usrp_info(size_t chan = 0) = 0;
/*!
- * Set the frontend specification.
- * \param spec the subdev spec markup string
- * \param mboard the motherboard index 0 to M-1
- */
- virtual void set_subdev_spec(const std::string &spec, size_t mboard = 0) = 0;
-
- /*!
- * Get the RX frontend specification.
- * \param mboard the motherboard index 0 to M-1
- * \return the frontend specification in use
- */
- virtual std::string get_subdev_spec(size_t mboard = 0) = 0;
-
- /*!
- * Set the sample rate for the usrp device.
- * \param rate a new rate in Sps
- */
- virtual void set_samp_rate(double rate) = 0;
-
- /*!
- * Get the sample rate for the usrp device.
- * This is the actual sample rate and may differ from the rate set.
- * \return the actual rate in Sps
- */
- 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
- * \return a tune result with the actual frequencies
- */
- virtual ::uhd::tune_result_t set_center_freq
- (const ::uhd::tune_request_t tune_request, size_t chan = 0) = 0;
-
- /*!
- * Tune the usrp device to the desired center frequency.
- * This is a wrapper around set center freq so that in this case,
- * the user can pass a single frequency in the call through swig.
- * \param freq the desired frequency in Hz
- * \param chan the channel index 0 to N-1
- * \return a tune result with the actual frequencies
- */
- ::uhd::tune_result_t set_center_freq(double freq, size_t chan = 0)
- {
- return set_center_freq(::uhd::tune_request_t(freq), chan);
- }
-
- /*!
- * Get the center frequency.
- * \param chan the channel index 0 to N-1
- * \return the frequency in Hz
- */
- virtual double get_center_freq(size_t chan = 0) = 0;
-
- /*!
- * Get the tunable frequency range.
- * \param chan the channel index 0 to N-1
- * \return the frequency range in Hz
- */
- virtual ::uhd::freq_range_t get_freq_range(size_t chan = 0) = 0;
-
- /*!
- * Set the gain for the dboard.
- * \param gain the gain in dB
- * \param chan the channel index 0 to N-1
- */
- virtual void set_gain(double gain, size_t chan = 0) = 0;
-
- /*!
- * Set the named gain on the dboard.
- * \param gain the gain in dB
- * \param name the name of the gain stage
- * \param chan the channel index 0 to N-1
- */
- virtual void set_gain(double gain,
- const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * Set the normalized gain.
- *
- * The normalized gain is always in [0, 1], regardless of the device.
- * 0 corresponds to minimum gain (usually 0 dB, but make sure to read the device
- * notes in the UHD manual) and 1 corresponds to maximum gain.
- * This will work for any UHD device. Use get_gain() to see which dB value
- * the normalized gain value corresponds to.
- *
- * Note that it is not possible to specify a gain name for this function.
- *
- * \throws A runtime_error if \p norm_gain is not within the valid range.
- *
- * \param norm_gain the gain in fractions of the gain range (must be 0 <= norm_gain <= 1)
- * \param chan the channel index 0 to N-1
- */
- virtual void set_normalized_gain(double norm_gain, size_t chan = 0) = 0;
-
- /*!
- * Get the actual dboard gain setting.
- * \param chan the channel index 0 to N-1
- * \return the actual gain in dB
- */
- virtual double get_gain(size_t chan = 0) = 0;
-
- /*!
- * Get the actual dboard gain setting of named stage.
- * \param name the name of the gain stage
- * \param chan the channel index 0 to N-1
- * \return the actual gain in dB
- */
- virtual double get_gain(const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * Returns the normalized gain.
- *
- * The normalized gain is always in [0, 1], regardless of the device.
- * See also set_normalized_gain().
- *
- * Note that it is not possible to specify a gain name for this function,
- * the result is over the entire gain chain.
- *
- * \param chan the channel index 0 to N-1
- */
- virtual double get_normalized_gain(size_t chan = 0) = 0;
-
- /*!
- * Get the actual dboard gain setting of named stage.
- * \param chan the channel index 0 to N-1
- * \return the actual gain in dB
- */
- virtual std::vector<std::string> get_gain_names(size_t chan = 0) = 0;
-
- /*!
- * Get the settable gain range.
- * \param chan the channel index 0 to N-1
- * \return the gain range in dB
- */
- virtual ::uhd::gain_range_t get_gain_range(size_t chan = 0) = 0;
-
- /*!
- * Get the settable gain range.
- * \param name the name of the gain stage
- * \param chan the channel index 0 to N-1
- * \return the gain range in dB
- */
- virtual ::uhd::gain_range_t get_gain_range(const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * Set the antenna to use.
- * \param ant the antenna string
- * \param chan the channel index 0 to N-1
- */
- virtual void set_antenna(const std::string &ant,
- size_t chan = 0) = 0;
-
- /*!
- * Get the antenna in use.
- * \param chan the channel index 0 to N-1
- * \return the antenna string
- */
- virtual std::string get_antenna(size_t chan = 0) = 0;
-
- /*!
- * Get a list of possible antennas.
- * \param chan the channel index 0 to N-1
- * \return a vector of antenna strings
- */
- virtual std::vector<std::string> get_antennas(size_t chan = 0) = 0;
-
- /*!
- * 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 the bandpass filter setting on the RF frontend.
- * \param chan the channel index 0 to N-1
- * \return bandwidth of the filter in Hz
- */
- virtual double get_bandwidth(size_t chan = 0) = 0;
-
- /*!
- * Get the bandpass filter range of the RF frontend.
- * \param chan the channel index 0 to N-1
- * \return the range of the filter bandwidth in Hz
- */
- virtual ::uhd::freq_range_t get_bandwidth_range(size_t chan = 0) = 0;
-
- /*!
* Enable/disable the automatic DC offset correction.
* The automatic correction subtracts out the long-run average.
*
@@ -377,221 +179,6 @@ namespace gr {
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_sensor(const std::string &name,
- size_t chan = 0) = 0;
-
- /*!
- * 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_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.
- * \param name the name of the sensor
- * \param mboard the motherboard index 0 to M-1
- * \return a sensor value object
- */
- virtual ::uhd::sensor_value_t get_mboard_sensor(const std::string &name,
- size_t mboard = 0) = 0;
-
- /*!
- * Get a list of possible motherboard sensor names.
- * \param mboard the motherboard index 0 to M-1
- * \return a vector of sensor names
- */
- virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0;
-
- /*!
- * 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
- */
- virtual double get_clock_rate(size_t mboard = 0) = 0;
-
- /*!
- * Set the master clock rate.
- * \param rate the new rate in Hz
- * \param mboard the motherboard index 0 to M-1
- */
- virtual void set_clock_rate(double rate, size_t mboard = 0) = 0;
-
- /*!
- * Get the current time registers.
- * \param mboard the motherboard index 0 to M-1
- * \return the current usrp time
- */
- virtual ::uhd::time_spec_t get_time_now(size_t mboard = 0) = 0;
-
- /*!
- * Get the time when the last pps pulse occured.
- * \param mboard the motherboard index 0 to M-1
- * \return the current usrp time
- */
- virtual ::uhd::time_spec_t get_time_last_pps(size_t mboard = 0) = 0;
-
- /*!
- * Sets the time registers immediately.
- * \param time_spec the new time
- * \param mboard the motherboard index 0 to M-1
- */
- virtual void set_time_now(const ::uhd::time_spec_t &time_spec,
- size_t mboard = 0) = 0;
-
- /*!
- * Set the time registers at the next pps.
- * \param time_spec the new time
- */
- virtual void set_time_next_pps(const ::uhd::time_spec_t &time_spec) = 0;
-
- /*!
- * Sync the time registers with an unknown pps edge.
- * \param time_spec the new time
- */
- 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
- */
- virtual ::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan = 0) = 0;
-
- /*!
- * Get access to the underlying uhd device object.
- *
- * NOTE: This function is only available in C++.
- * \return the multi usrp device object
- */
- virtual ::uhd::usrp::multi_usrp::sptr get_device(void) = 0;
-
- /*!
- * Perform write on the user configuration register bus. These
- * only exist if the user has implemented custom setting
- * registers in the device FPGA.
- * \param addr 8-bit register address
- * \param data 32-bit register value
- * \param mboard which motherboard to set the user register
- */
- virtual void set_user_register(const uint8_t addr,
- const uint32_t data,
- size_t mboard = 0) = 0;
-
- /*!
- * Update the stream args for this device.
- *
- * This update will only take effect after a restart of the
- * streaming, or before streaming and after construction.
- * This will also delete the current streamer.
- * Note you cannot change the I/O signature of this block using
- * this function, or it will throw.
- *
- * It is possible to leave the 'channels' fields of \p stream_args
- * unset. In this case, the previous channels field is used.
- *
- * \param stream_args New stream args.
- * \throws std::runtime_error if new settings are invalid.
- */
- virtual void set_stream_args(const ::uhd::stream_args_t &stream_args) = 0;
-
- /*!
* Convenience function for finite data acquisition.
* This is not to be used with the scheduler; rather,
* one can request samples from the USRP in python.
diff --git a/gr-uhd/lib/CMakeLists.txt b/gr-uhd/lib/CMakeLists.txt
index b3ead137af..531bd40b09 100644
--- a/gr-uhd/lib/CMakeLists.txt
+++ b/gr-uhd/lib/CMakeLists.txt
@@ -46,6 +46,7 @@ link_directories(${LOG4CPP_LIBRARY_DIRS})
# Setup library
########################################################################
list(APPEND gr_uhd_sources
+ usrp_block_impl.cc
usrp_source_impl.cc
usrp_sink_impl.cc
amsg_source_impl.cc
diff --git a/gr-uhd/lib/usrp_block_impl.cc b/gr-uhd/lib/usrp_block_impl.cc
new file mode 100644
index 0000000000..1977b89a3a
--- /dev/null
+++ b/gr-uhd/lib/usrp_block_impl.cc
@@ -0,0 +1,696 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usrp_block_impl.h"
+#include <boost/make_shared.hpp>
+
+using namespace gr::uhd;
+
+const double usrp_block_impl::LOCK_TIMEOUT = 1.5;
+
+const pmt::pmt_t CMD_CHAN_KEY = pmt::mp("chan");
+const pmt::pmt_t CMD_GAIN_KEY = pmt::mp("gain");
+const pmt::pmt_t CMD_FREQ_KEY = pmt::mp("freq");
+const pmt::pmt_t CMD_LO_OFFSET_KEY = pmt::mp("lo_offset");
+const pmt::pmt_t CMD_TUNE_KEY = pmt::mp("tune");
+const pmt::pmt_t CMD_LO_FREQ_KEY = pmt::mp("lo_freq");
+const pmt::pmt_t CMD_DSP_FREQ_KEY = pmt::mp("dsp_freq");
+const pmt::pmt_t CMD_RATE_KEY = pmt::mp("rate");
+const pmt::pmt_t CMD_BANDWIDTH_KEY = pmt::mp("bandwidth");
+const pmt::pmt_t CMD_TIME_KEY = pmt::mp("time");
+const pmt::pmt_t CMD_MBOARD_KEY = pmt::mp("mboard");
+const pmt::pmt_t CMD_ANTENNA_KEY = pmt::mp("antenna");
+
+
+/**********************************************************************
+ * Structors
+ *********************************************************************/
+usrp_block::usrp_block(
+ const std::string &name,
+ gr::io_signature::sptr input_signature,
+ gr::io_signature::sptr output_signature
+) : sync_block(name, input_signature, output_signature)
+{
+ // nop
+}
+
+usrp_block_impl::usrp_block_impl(
+ const ::uhd::device_addr_t &device_addr,
+ const ::uhd::stream_args_t &stream_args,
+ const std::string &ts_tag_name
+) : _stream_args(stream_args),
+ _nchan(stream_args.channels.size()),
+ _stream_now(_nchan == 1 and ts_tag_name.empty()),
+ _start_time_set(false),
+ _curr_tune_req(stream_args.channels.size(), ::uhd::tune_request_t()),
+ _chans_to_tune(stream_args.channels.size())
+{
+ // TODO remove this when we update UHD
+ 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);
+
+ _check_mboard_sensors_locked();
+
+ // Set up message ports:
+ message_port_register_in(pmt::mp("command"));
+ set_msg_handler(
+ pmt::mp("command"),
+ boost::bind(&usrp_block_impl::msg_handler_command, this, _1)
+ );
+
+// cuz we lazy:
+#define REGISTER_CMD_HANDLER(key, _handler) register_msg_cmd_handler(key, boost::bind(&usrp_block_impl::_handler, this, _1, _2, _3))
+ // Register default command handlers:
+ REGISTER_CMD_HANDLER(CMD_FREQ_KEY, _cmd_handler_freq);
+ REGISTER_CMD_HANDLER(CMD_GAIN_KEY, _cmd_handler_gain);
+ REGISTER_CMD_HANDLER(CMD_LO_OFFSET_KEY, _cmd_handler_looffset);
+ REGISTER_CMD_HANDLER(CMD_TUNE_KEY, _cmd_handler_tune);
+ REGISTER_CMD_HANDLER(CMD_LO_FREQ_KEY, _cmd_handler_lofreq);
+ REGISTER_CMD_HANDLER(CMD_DSP_FREQ_KEY, _cmd_handler_dspfreq);
+ REGISTER_CMD_HANDLER(CMD_RATE_KEY, _cmd_handler_rate);
+ REGISTER_CMD_HANDLER(CMD_BANDWIDTH_KEY, _cmd_handler_bw);
+ REGISTER_CMD_HANDLER(CMD_ANTENNA_KEY, _cmd_handler_antenna);
+}
+
+usrp_block_impl::~usrp_block_impl()
+{
+ // nop
+}
+
+/**********************************************************************
+ * Helpers
+ *********************************************************************/
+void usrp_block_impl::_update_stream_args(const ::uhd::stream_args_t &stream_args_)
+{
+ ::uhd::stream_args_t stream_args(stream_args_);
+ if (stream_args.channels.empty()) {
+ stream_args.channels = _stream_args.channels;
+ }
+ if (stream_args.cpu_format != _stream_args.cpu_format ||
+ stream_args.channels.size() != _stream_args.channels.size()) {
+ throw std::runtime_error("Cannot change I/O signatures while updating stream args!");
+ }
+ _stream_args = stream_args;
+}
+
+bool usrp_block_impl::_wait_for_locked_sensor(
+ std::vector<std::string> sensor_names,
+ const std::string &sensor_name,
+ get_sensor_fn_t get_sensor_fn
+){
+ if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) == sensor_names.end())
+ return true;
+
+ boost::system_time start = boost::get_system_time();
+ boost::system_time first_lock_time;
+
+ while (true) {
+ if ((not first_lock_time.is_not_a_date_time()) and
+ (boost::get_system_time() > (first_lock_time + boost::posix_time::seconds(LOCK_TIMEOUT)))) {
+ break;
+ }
+
+ if (get_sensor_fn(sensor_name).to_bool()) {
+ if (first_lock_time.is_not_a_date_time())
+ first_lock_time = boost::get_system_time();
+ }
+ else {
+ first_lock_time = boost::system_time(); //reset to 'not a date time'
+
+ if (boost::get_system_time() > (start + boost::posix_time::seconds(LOCK_TIMEOUT))){
+ return false;
+ }
+ }
+
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ }
+
+ return true;
+}
+
+bool usrp_block_impl::_unpack_chan_command(
+ std::string &command,
+ pmt::pmt_t &cmd_val,
+ int &chan,
+ const pmt::pmt_t &cmd_pmt
+) {
+ try {
+ chan = -1; // Default value
+ if (pmt::is_tuple(cmd_pmt) and (pmt::length(cmd_pmt) == 2 or pmt::length(cmd_pmt) == 3)) {
+ command = pmt::symbol_to_string(pmt::tuple_ref(cmd_pmt, 0));
+ cmd_val = pmt::tuple_ref(cmd_pmt, 1);
+ if (pmt::length(cmd_pmt) == 3) {
+ chan = pmt::to_long(pmt::tuple_ref(cmd_pmt, 2));
+ }
+ }
+ else if (pmt::is_pair(cmd_pmt)) {
+ command = pmt::symbol_to_string(pmt::car(cmd_pmt));
+ cmd_val = pmt::cdr(cmd_pmt);
+ if (pmt::is_pair(cmd_val)) {
+ chan = pmt::to_long(pmt::car(cmd_val));
+ cmd_val = pmt::cdr(cmd_val);
+ }
+ }
+ else {
+ return false;
+ }
+ } catch (pmt::wrong_type w) {
+ return false;
+ }
+ return true;
+}
+
+bool usrp_block_impl::_check_mboard_sensors_locked()
+{
+ bool clocks_locked = true;
+
+ // Check ref lock for all mboards
+ for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) {
+ std::string sensor_name = "ref_locked";
+ if (_dev->get_clock_source(mboard_index) == "internal") {
+ continue;
+ }
+ else if (_dev->get_clock_source(mboard_index) == "mimo") {
+ sensor_name = "mimo_locked";
+ }
+ if (not _wait_for_locked_sensor(
+ get_mboard_sensor_names(mboard_index),
+ sensor_name,
+ boost::bind(&usrp_block_impl::get_mboard_sensor, this, _1, mboard_index)
+ )) {
+ GR_LOG_WARN(d_logger, boost::format("Sensor '%s' failed to lock within timeout on motherboard %d.") % sensor_name % mboard_index);
+ clocks_locked = false;
+ }
+ }
+
+ return clocks_locked;
+}
+
+void
+usrp_block_impl::_set_center_freq_from_internals_allchans()
+{
+ while (_chans_to_tune.any()) {
+ // This resets() bits, so this loop should not run indefinitely
+ _set_center_freq_from_internals(_chans_to_tune.find_first());
+ }
+}
+
+
+/**********************************************************************
+ * Public API calls
+ *********************************************************************/
+::uhd::sensor_value_t
+usrp_block_impl::get_mboard_sensor(const std::string &name,
+ size_t mboard)
+{
+ return _dev->get_mboard_sensor(name, mboard);
+}
+
+std::vector<std::string>
+usrp_block_impl::get_mboard_sensor_names(size_t mboard)
+{
+ return _dev->get_mboard_sensor_names(mboard);
+}
+
+void
+usrp_block_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
+ size_t mboard)
+{
+ return _dev->set_clock_config(clock_config, mboard);
+}
+
+void
+usrp_block_impl::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
+usrp_block_impl::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>
+usrp_block_impl::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
+usrp_block_impl::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
+usrp_block_impl::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>
+usrp_block_impl::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
+usrp_block_impl::get_clock_rate(size_t mboard)
+{
+ return _dev->get_master_clock_rate(mboard);
+}
+
+void
+usrp_block_impl::set_clock_rate(double rate, size_t mboard)
+{
+ return _dev->set_master_clock_rate(rate, mboard);
+}
+
+::uhd::time_spec_t
+usrp_block_impl::get_time_now(size_t mboard)
+{
+ return _dev->get_time_now(mboard);
+}
+
+::uhd::time_spec_t
+usrp_block_impl::get_time_last_pps(size_t mboard)
+{
+ return _dev->get_time_last_pps(mboard);
+}
+
+std::vector<std::string>
+usrp_block_impl::get_gpio_banks(const size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_GPIO_API
+ return _dev->get_gpio_banks(mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+boost::uint32_t
+usrp_block_impl::get_gpio_attr(
+ const std::string &bank,
+ const std::string &attr,
+ const size_t mboard
+) {
+#ifdef UHD_USRP_MULTI_USRP_GPIO_API
+ return _dev->get_gpio_attr(bank, attr, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
+ size_t mboard)
+{
+ return _dev->set_time_now(time_spec, mboard);
+}
+
+void
+usrp_block_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
+{
+ return _dev->set_time_next_pps(time_spec);
+}
+
+void
+usrp_block_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
+{
+ return _dev->set_time_unknown_pps(time_spec);
+}
+
+void
+usrp_block_impl::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
+usrp_block_impl::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
+}
+
+void
+usrp_block_impl::set_user_register(const uint8_t addr,
+ const uint32_t data,
+ size_t mboard)
+{
+#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
+ _dev->set_user_register(addr, data, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+void
+usrp_block_impl::set_gpio_attr(
+ const std::string &bank,
+ const std::string &attr,
+ const boost::uint32_t value,
+ const boost::uint32_t mask,
+ const size_t mboard
+) {
+#ifdef UHD_USRP_MULTI_USRP_GPIO_API
+ return _dev->set_gpio_attr(bank, attr, value, mask, mboard);
+#else
+ throw std::runtime_error("not implemented in this version");
+#endif
+}
+
+::uhd::usrp::multi_usrp::sptr
+usrp_block_impl::get_device(void)
+{
+ return _dev;
+}
+
+/**********************************************************************
+ * External Interfaces
+ *********************************************************************/
+void
+usrp_block_impl::setup_rpc()
+{
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<usrp_block, double>(
+ alias(), "samp_rate",
+ &usrp_block::get_samp_rate,
+ pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
+ "sps", "Sample Rate", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP))
+ );
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<usrp_block, double>(
+ alias(), "samp_rate",
+ &usrp_block::set_samp_rate,
+ pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
+ "sps", "Sample Rate",
+ RPC_PRIVLVL_MIN, DISPNULL))
+ );
+#endif /* GR_CTRLPORT */
+}
+
+void usrp_block_impl::msg_handler_command(pmt::pmt_t msg)
+{
+ // Legacy code back compat: If we receive a tuple, we convert
+ // it to a dict, and call the function again. Yep, this comes
+ // at a slight performance hit. Sometime in the future, we can
+ // hopefully remove this:
+ if (pmt::is_tuple(msg)) {
+ if (pmt::length(msg) != 2 && pmt::length(msg) != 3) {
+ GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command PMT: %s") % msg);
+ return;
+ }
+ pmt::pmt_t new_msg = pmt::make_dict();
+ new_msg = pmt::dict_add(new_msg, pmt::tuple_ref(msg, 0), pmt::tuple_ref(msg, 1));
+ if (pmt::length(msg) == 3) {
+ new_msg = pmt::dict_add(new_msg, pmt::mp("chan"), pmt::tuple_ref(msg, 2));
+ }
+ GR_LOG_WARN(d_debug_logger, boost::format("Using legacy message format (tuples): %s") % msg);
+ return msg_handler_command(new_msg);
+ }
+ // End of legacy backward compat code.
+
+ // Turn pair into dict
+ if (!pmt::is_dict(msg)) {
+ GR_LOG_ERROR(d_logger, boost::format("Command message is neither dict nor pair: %s") % msg);
+ return;
+ }
+
+ // OK, here comes the horrible part. Pairs pass is_dict(), but they're not dicts. Such dicks.
+ try {
+ // This will fail if msg is a pair:
+ pmt::pmt_t keys = pmt::dict_keys(msg);
+ } catch (const pmt::wrong_type &e) {
+ // So we fix it:
+ GR_LOG_DEBUG(d_debug_logger, boost::format("Converting pair to dict: %s") % msg);
+ msg = pmt::dict_add(pmt::make_dict(), pmt::car(msg), pmt::cdr(msg));
+ }
+
+ /*** Start the actual message processing *************************/
+ /// 1) Check if there's a time stamp
+ if (pmt::dict_has_key(msg, CMD_TIME_KEY)) {
+ size_t mboard_index = pmt::to_long(
+ pmt::dict_ref(
+ msg, CMD_MBOARD_KEY,
+ pmt::from_long( ::uhd::usrp::multi_usrp::ALL_MBOARDS ) // Default to all mboards
+ )
+ );
+ pmt::pmt_t timespec_p = pmt::dict_ref(msg, CMD_TIME_KEY, pmt::PMT_NIL);
+ if (timespec_p == pmt::PMT_NIL) {
+ clear_command_time(mboard_index);
+ } else {
+ ::uhd::time_spec_t timespec(
+ time_t(pmt::to_uint64(pmt::car(timespec_p))), // Full secs
+ pmt::to_double(pmt::cdr(timespec_p)) // Frac secs
+ );
+ GR_LOG_DEBUG(d_debug_logger, boost::format("Setting command time on mboard %d") % mboard_index);
+ set_command_time(timespec, mboard_index);
+ }
+ }
+
+ /// 2) Read chan value
+ int chan = int(pmt::to_long(
+ pmt::dict_ref(
+ msg, CMD_CHAN_KEY,
+ pmt::from_long(-1) // Default to all chans
+ )
+ ));
+
+ /// 3) Loop through all the values
+ GR_LOG_DEBUG(d_debug_logger, boost::format("Processing command message %s") % msg);
+ pmt::pmt_t msg_items = pmt::dict_items(msg);
+ for (size_t i = 0; i < pmt::length(msg_items); i++) {
+ try {
+ dispatch_msg_cmd_handler(
+ pmt::car(pmt::nth(i, msg_items)),
+ pmt::cdr(pmt::nth(i, msg_items)),
+ chan, msg
+ );
+ } catch (pmt::wrong_type &e) {
+ GR_LOG_ALERT(d_logger, boost::format("Invalid command value for key %s: %s") % pmt::car(pmt::nth(i, msg_items)) % pmt::cdr(pmt::nth(i, msg_items)));
+ break;
+ }
+ }
+
+ /// 4) Check if we need to re-tune
+ _set_center_freq_from_internals_allchans();
+}
+
+
+void usrp_block_impl::dispatch_msg_cmd_handler(const pmt::pmt_t &cmd, const pmt::pmt_t &val, int chan, pmt::pmt_t &msg)
+{
+ if (_msg_cmd_handlers.has_key(cmd)) {
+ _msg_cmd_handlers[cmd](val, chan, msg);
+ }
+}
+
+void usrp_block_impl::register_msg_cmd_handler(const pmt::pmt_t &cmd, cmd_handler_t handler)
+{
+ _msg_cmd_handlers[cmd] = handler;
+}
+
+void usrp_block_impl::_update_curr_tune_req(::uhd::tune_request_t &tune_req, int chan)
+{
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ _update_curr_tune_req(tune_req, int(i));
+ }
+ return;
+ }
+
+ if (tune_req.target_freq != _curr_tune_req[chan].target_freq ||
+ tune_req.rf_freq_policy != _curr_tune_req[chan].rf_freq_policy ||
+ tune_req.rf_freq != _curr_tune_req[chan].rf_freq ||
+ tune_req.dsp_freq != _curr_tune_req[chan].dsp_freq ||
+ tune_req.dsp_freq_policy != _curr_tune_req[chan].dsp_freq_policy
+ ) {
+ _curr_tune_req[chan] = tune_req;
+ _chans_to_tune.set(chan);
+ }
+}
+
+// Default handlers:
+void usrp_block_impl::_cmd_handler_freq(const pmt::pmt_t &freq_, int chan, const pmt::pmt_t &msg)
+{
+ double freq = pmt::to_double(freq_);
+ ::uhd::tune_request_t new_tune_reqest(freq);
+ if (pmt::dict_has_key(msg, CMD_LO_OFFSET_KEY)) {
+ double lo_offset = pmt::to_double(pmt::dict_ref(msg, CMD_LO_OFFSET_KEY, pmt::PMT_NIL));
+ new_tune_reqest = ::uhd::tune_request_t(freq, lo_offset);
+ }
+
+ _update_curr_tune_req(new_tune_reqest, chan);
+}
+
+void usrp_block_impl::_cmd_handler_looffset(const pmt::pmt_t &lo_offset, int chan, const pmt::pmt_t &msg)
+{
+ if (pmt::dict_has_key(msg, CMD_FREQ_KEY)) {
+ // Then it's already taken care of
+ return;
+ }
+
+ double lo_offs = pmt::to_double(lo_offset);
+ ::uhd::tune_request_t new_tune_request = _curr_tune_req[chan];
+ new_tune_request.rf_freq = new_tune_request.target_freq + lo_offs;
+ new_tune_request.rf_freq_policy = ::uhd::tune_request_t::POLICY_MANUAL;
+ new_tune_request.dsp_freq_policy = ::uhd::tune_request_t::POLICY_AUTO;
+
+ _update_curr_tune_req(new_tune_request, chan);
+}
+
+void usrp_block_impl::_cmd_handler_gain(const pmt::pmt_t &gain_, int chan, const pmt::pmt_t &msg)
+{
+ double gain = pmt::to_double(gain_);
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ set_gain(gain, i);
+ }
+ return;
+ }
+
+ set_gain(gain, chan);
+}
+
+void usrp_block_impl::_cmd_handler_antenna(const pmt::pmt_t &ant, int chan, const pmt::pmt_t &msg)
+{
+ const std::string antenna(pmt::symbol_to_string(ant));
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ set_antenna(antenna, i);
+ }
+ return;
+ }
+
+ set_antenna(antenna, chan);
+}
+
+void usrp_block_impl::_cmd_handler_rate(const pmt::pmt_t &rate_, int, const pmt::pmt_t &)
+{
+ const double rate = pmt::to_double(rate_);
+ set_samp_rate(rate);
+}
+
+void usrp_block_impl::_cmd_handler_tune(const pmt::pmt_t &tune, int chan, const pmt::pmt_t &msg)
+{
+ double freq = pmt::to_double(pmt::car(tune));
+ double lo_offset = pmt::to_double(pmt::cdr(tune));
+ ::uhd::tune_request_t new_tune_reqest(freq, lo_offset);
+ _update_curr_tune_req(new_tune_reqest, chan);
+}
+
+void usrp_block_impl::_cmd_handler_bw(const pmt::pmt_t &bw, int chan, const pmt::pmt_t &msg)
+{
+ double bandwidth = pmt::to_double(bw);
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ set_bandwidth(bandwidth, i);
+ }
+ return;
+ }
+
+ set_bandwidth(bandwidth, chan);
+}
+
+void usrp_block_impl::_cmd_handler_lofreq(const pmt::pmt_t &lofreq, int chan, const pmt::pmt_t &msg)
+{
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ _cmd_handler_lofreq(lofreq, int(i), msg);
+ }
+ return;
+ }
+
+ ::uhd::tune_request_t new_tune_request = _curr_tune_req[chan];
+ new_tune_request.rf_freq = pmt::to_double(lofreq);
+ if (pmt::dict_has_key(msg, CMD_DSP_FREQ_KEY)) {
+ new_tune_request.dsp_freq = pmt::to_double(pmt::dict_ref(msg, CMD_DSP_FREQ_KEY, pmt::PMT_NIL));
+ }
+ new_tune_request.rf_freq_policy = ::uhd::tune_request_t::POLICY_MANUAL;
+ new_tune_request.dsp_freq_policy = ::uhd::tune_request_t::POLICY_MANUAL;
+
+ _update_curr_tune_req(new_tune_request, chan);
+}
+
+void usrp_block_impl::_cmd_handler_dspfreq(const pmt::pmt_t &dspfreq, int chan, const pmt::pmt_t &msg)
+{
+ if (pmt::dict_has_key(msg, CMD_LO_FREQ_KEY)) {
+ // Then it's already dealt with
+ return;
+ }
+
+ if (chan == -1) {
+ for (size_t i = 0; i < _nchan; i++) {
+ _cmd_handler_dspfreq(dspfreq, int(i), msg);
+ }
+ return;
+ }
+
+ ::uhd::tune_request_t new_tune_request = _curr_tune_req[chan];
+ new_tune_request.dsp_freq = pmt::to_double(dspfreq);
+ new_tune_request.rf_freq_policy = ::uhd::tune_request_t::POLICY_MANUAL;
+ new_tune_request.dsp_freq_policy = ::uhd::tune_request_t::POLICY_MANUAL;
+
+ _update_curr_tune_req(new_tune_request, chan);
+}
+
diff --git a/gr-uhd/lib/usrp_block_impl.h b/gr-uhd/lib/usrp_block_impl.h
new file mode 100644
index 0000000000..2158d542bc
--- /dev/null
+++ b/gr-uhd/lib/usrp_block_impl.h
@@ -0,0 +1,241 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2015 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_UHD_BLOCK_IMPL_H
+#define INCLUDED_GR_UHD_BLOCK_IMPL_H
+
+#include <gnuradio/uhd/usrp_block.h>
+#include <pmt/pmt.h>
+#include <uhd/usrp/multi_usrp.hpp>
+#include <boost/dynamic_bitset.hpp>
+#include <boost/bind.hpp>
+
+#define SET_CENTER_FREQ_FROM_INTERNALS(usrp_class, tune_method) \
+ ::uhd::tune_result_t \
+ usrp_class::_set_center_freq_from_internals(size_t chan) \
+ { \
+ _chans_to_tune.reset(chan); \
+ return _dev->tune_method(_curr_tune_req[chan], _stream_args.channels[chan]); \
+ }
+
+namespace gr {
+ namespace uhd {
+
+ class usrp_block_impl : virtual public usrp_block
+ {
+ public:
+ typedef boost::function< ::uhd::sensor_value_t (const std::string&)> get_sensor_fn_t;
+ typedef boost::function<void(const pmt::pmt_t &, int, const pmt::pmt_t &)> cmd_handler_t;
+
+ static const double LOCK_TIMEOUT;
+
+ /**********************************************************************
+ * Public API calls (see usrp_block.h for docs)
+ **********************************************************************/
+ // Getters
+ ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard);
+ std::vector<std::string> get_mboard_sensor_names(size_t mboard);
+ std::string get_time_source(const size_t mboard);
+ std::vector<std::string> get_time_sources(const size_t mboard);
+ std::string get_clock_source(const size_t mboard);
+ std::vector<std::string> get_clock_sources(const size_t mboard);
+ double get_clock_rate(size_t mboard);
+ ::uhd::time_spec_t get_time_now(size_t mboard = 0);
+ ::uhd::time_spec_t get_time_last_pps(size_t mboard);
+ ::uhd::usrp::multi_usrp::sptr get_device(void);
+ std::vector<std::string> get_gpio_banks(const size_t mboard);
+ boost::uint32_t get_gpio_attr(
+ const std::string &bank,
+ const std::string &attr,
+ const size_t mboard = 0
+ );
+
+ // Setters
+ void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t mboard);
+ void set_time_source(const std::string &source, const size_t mboard);
+ void set_clock_source(const std::string &source, const size_t mboard);
+ void set_clock_rate(double rate, size_t mboard);
+ void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
+ void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
+ void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
+ void set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard);
+ void set_user_register(const uint8_t addr, const uint32_t data, size_t mboard);
+ void clear_command_time(size_t mboard);
+ void set_gpio_attr(
+ const std::string &bank,
+ const std::string &attr,
+ const boost::uint32_t value,
+ const boost::uint32_t mask,
+ const size_t mboard
+ );
+
+ // RPC
+ void setup_rpc();
+
+ /**********************************************************************
+ * Structors
+ * ********************************************************************/
+ virtual ~usrp_block_impl();
+ protected:
+ /*! \brief Components common to USRP sink and source.
+ *
+ * \param device_addr Device address + options
+ * \param stream_args Stream args (cpu format, otw format...)
+ * \param ts_tag_name If this block produces or consumes stream tags, enter the corresponding tag name here
+ */
+ usrp_block_impl(
+ const ::uhd::device_addr_t &device_addr,
+ const ::uhd::stream_args_t &stream_args,
+ const std::string &ts_tag_name
+ );
+
+ /**********************************************************************
+ * Command Interface
+ **********************************************************************/
+ //! Receives commands and handles them
+ void msg_handler_command(pmt::pmt_t msg);
+
+ //! For a given argument, call the associated handler, or if none exists,
+ // show a warning through the logging interface.
+ void dispatch_msg_cmd_handler(const pmt::pmt_t &cmd, const pmt::pmt_t &val, int chan, pmt::pmt_t &msg);
+
+ //! Register a new handler for command key \p cmd
+ void register_msg_cmd_handler(const pmt::pmt_t &cmd, cmd_handler_t handler);
+
+
+ // Default handlers
+ void _cmd_handler_freq(const pmt::pmt_t &freq, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_looffset(const pmt::pmt_t &lo_offset, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_gain(const pmt::pmt_t &gain, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_antenna(const pmt::pmt_t &ant, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_rate(const pmt::pmt_t &rate, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_tune(const pmt::pmt_t &tune, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_bw(const pmt::pmt_t &bw, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_lofreq(const pmt::pmt_t &lofreq, int chan, const pmt::pmt_t &msg);
+ void _cmd_handler_dspfreq(const pmt::pmt_t &dspfreq, int chan, const pmt::pmt_t &msg);
+
+ /**********************************************************************
+ * Helpers
+ **********************************************************************/
+ bool _check_mboard_sensors_locked();
+
+ void _update_stream_args(const ::uhd::stream_args_t &stream_args_);
+
+ // should be const, doesn't work though 'cause missing operator=() for tune_request_t
+ void _update_curr_tune_req(::uhd::tune_request_t &tune_req, int chan);
+
+ /*! \brief Wait until a timeout or a sensor returns 'locked'.
+ *
+ * If a given sensor is not found, this still returns 'true', so we don't throw
+ * errors or warnings if a sensor wasn't implemented.
+ *
+ * \returns true if the sensor locked in time or doesn't exist
+ */
+ bool _wait_for_locked_sensor(
+ std::vector<std::string> sensor_names,
+ const std::string &sensor_name,
+ get_sensor_fn_t get_sensor_fn
+ );
+
+ //! Helper function for msg_handler_command:
+ // - Extracts command and the command value from the command PMT
+ // - Returns true if the command PMT is well formed
+ // - If a channel is given, return that as well, otherwise set the channel to -1
+ static bool _unpack_chan_command(
+ std::string &command,
+ pmt::pmt_t &cmd_val,
+ int &chan,
+ const pmt::pmt_t &cmd_pmt
+ );
+
+ //! Helper function for msg_handler_command:
+ // - Sets a value in vector_to_update to cmd_val, depending on chan
+ // - If chan is a positive integer, it will set vector_to_update[chan]
+ // - If chan is -1, it depends on minus_one_updates_all:
+ // - Either set vector_to_update[0] or
+ // - Set *all* entries in vector_to_update
+ // - Returns a dynamic_bitset, all indexes that where changed in
+ // vector_to_update are set to 1
+ template <typename T>
+ static boost::dynamic_bitset<> _update_vector_from_cmd_val(
+ std::vector<T> &vector_to_update,
+ int chan,
+ const T cmd_val,
+ bool minus_one_updates_all = false
+ ) {
+ boost::dynamic_bitset<> vals_updated(vector_to_update.size());
+ if (chan == -1) {
+ if (minus_one_updates_all) {
+ for (size_t i = 0; i < vector_to_update.size(); i++) {
+ if (vector_to_update[i] != cmd_val) {
+ vals_updated[i] = true;
+ vector_to_update[i] = cmd_val;
+ }
+ }
+ return vals_updated;
+ }
+ chan = 0;
+ }
+ if (vector_to_update[chan] != cmd_val) {
+ vector_to_update[chan] = cmd_val;
+ vals_updated[chan] = true;
+ }
+
+ return vals_updated;
+ }
+
+ //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+ virtual ::uhd::tune_result_t _set_center_freq_from_internals(size_t chan) = 0;
+
+ //! Calls _set_center_freq_from_internals() on all channels
+ void _set_center_freq_from_internals_allchans();
+
+ /**********************************************************************
+ * Members
+ *********************************************************************/
+ //! Shared pointer to the underlying multi_usrp object
+ ::uhd::usrp::multi_usrp::sptr _dev;
+ ::uhd::stream_args_t _stream_args;
+ boost::shared_ptr< ::uhd::io_type_t > _type;
+ //! Number of channels (i.e. number of in- or outputs)
+ size_t _nchan;
+ bool _stream_now;
+ ::uhd::time_spec_t _start_time;
+ bool _start_time_set;
+
+ /****** Command interface related **********/
+ //! Stores a list of commands for later execution
+ std::vector<pmt::pmt_t> _pending_cmds;
+ //! Shadows the last value we told the USRP to tune to for every channel
+ // (this is not necessarily the true value the USRP is currently tuned to!).
+ std::vector< ::uhd::tune_request_t > _curr_tune_req;
+ boost::dynamic_bitset<> _chans_to_tune;
+
+ //! Stores the individual command handlers
+ ::uhd::dict<pmt::pmt_t, cmd_handler_t> _msg_cmd_handlers;
+ };
+
+ } /* namespace uhd */
+} /* namespace gr */
+
+#endif /* INCLUDED_GR_UHD_BLOCK_IMPL_H */
+
diff --git a/gr-uhd/lib/usrp_common.h b/gr-uhd/lib/usrp_common.h
deleted file mode 100644
index 41f443922c..0000000000
--- a/gr-uhd/lib/usrp_common.h
+++ /dev/null
@@ -1,211 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2014 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_GR_UHD_USRP_COMMON_H
-#define INCLUDED_GR_UHD_USRP_COMMON_H
-
-#include <pmt/pmt.h>
-#include <boost/dynamic_bitset.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/bind.hpp>
-#include <boost/thread.hpp>
-#include <uhd/usrp/multi_usrp.hpp>
-#include <uhd/convert.hpp>
-#include <iostream>
-
-namespace gr {
- namespace uhd {
- typedef boost::function< ::uhd::sensor_value_t (const std::string&)> get_sensor_fn_t;
-
- static const double LOCK_TIMEOUT = 1.5; // s
-
- //! Helper function for msg_handler_command:
- // - Extracts command and the command value from the command PMT
- // - Returns true if the command PMT is well formed
- // - If a channel is given, return that as well, otherwise set the channel to -1
- static bool _unpack_chan_command(
- std::string &command,
- pmt::pmt_t &cmd_val,
- int &chan,
- const pmt::pmt_t &cmd_pmt
- ) {
- try {
- chan = -1; // Default value
- if (pmt::is_tuple(cmd_pmt) and (pmt::length(cmd_pmt) == 2 or pmt::length(cmd_pmt) == 3)) {
- command = pmt::symbol_to_string(pmt::tuple_ref(cmd_pmt, 0));
- cmd_val = pmt::tuple_ref(cmd_pmt, 1);
- if (pmt::length(cmd_pmt) == 3) {
- chan = pmt::to_long(pmt::tuple_ref(cmd_pmt, 2));
- }
- }
- else if (pmt::is_pair(cmd_pmt)) {
- command = pmt::symbol_to_string(pmt::car(cmd_pmt));
- cmd_val = pmt::cdr(cmd_pmt);
- if (pmt::is_pair(cmd_val)) {
- chan = pmt::to_long(pmt::car(cmd_val));
- cmd_val = pmt::cdr(cmd_val);
- }
- }
- else {
- return false;
- }
- } catch (pmt::wrong_type w) {
- return false;
- }
- return true;
- }
-
- //! Helper function for msg_handler_command:
- // - Sets a value in vector_to_update to cmd_val, depending on chan
- // - If chan is a positive integer, it will set vector_to_update[chan]
- // - If chan is -1, it depends on minus_one_updates_all:
- // - Either set vector_to_update[0] or
- // - Set *all* entries in vector_to_update
- // - Returns a dynamic_bitset, all indexes that where changed in
- // vector_to_update are set to 1
- template <typename T>
- static boost::dynamic_bitset<> _update_vector_from_cmd_val(
- std::vector<T> &vector_to_update,
- int chan,
- const T cmd_val,
- bool minus_one_updates_all = false
- ) {
- boost::dynamic_bitset<> vals_updated(vector_to_update.size());
- if (chan == -1) {
- if (minus_one_updates_all) {
- for (size_t i = 0; i < vector_to_update.size(); i++) {
- if (vector_to_update[i] != cmd_val) {
- vals_updated[i] = true;
- vector_to_update[i] = cmd_val;
- }
- }
- return vals_updated;
- }
- chan = 0;
- }
- if (vector_to_update[chan] != cmd_val) {
- vector_to_update[chan] = cmd_val;
- vals_updated[chan] = true;
- }
-
- return vals_updated;
- }
-
-
- /*! \brief Components common to USRP sink and source.
- *
- * \param device_addr Device address + options
- * \param stream_args Stream args (cpu format, otw format...)
- * \param ts_tag_name If this block produces or consumes stream tags, enter the corresponding tag name here
- */
- class usrp_common_impl
- {
- public:
- usrp_common_impl(
- const ::uhd::device_addr_t &device_addr,
- const ::uhd::stream_args_t &stream_args,
- const std::string &ts_tag_name
- ) :
- _stream_args(stream_args),
- _nchan(stream_args.channels.size()),
- _stream_now(_nchan == 1 and ts_tag_name.empty()),
- _start_time_set(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);
- _dev = ::uhd::usrp::multi_usrp::make(device_addr);
- };
-
- ~usrp_common_impl() {};
-
- protected:
- /*! \brief Wait until a timeout or a sensor returns 'locked'.
- *
- * If a given sensor is not found, this still returns 'true', so we don't throw
- * errors or warnings if a sensor wasn't implemented.
- */
- bool _wait_for_locked_sensor(
- std::vector<std::string> sensor_names,
- const std::string &sensor_name,
- get_sensor_fn_t get_sensor_fn
- ){
- if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) == sensor_names.end())
- return true;
-
- boost::system_time start = boost::get_system_time();
- boost::system_time first_lock_time;
-
- while (true) {
- if ((not first_lock_time.is_not_a_date_time()) and
- (boost::get_system_time() > (first_lock_time + boost::posix_time::seconds(LOCK_TIMEOUT)))) {
- break;
- }
-
- if (get_sensor_fn(sensor_name).to_bool()) {
- if (first_lock_time.is_not_a_date_time())
- first_lock_time = boost::get_system_time();
- }
- else {
- first_lock_time = boost::system_time(); //reset to 'not a date time'
-
- if (boost::get_system_time() > (start + boost::posix_time::seconds(LOCK_TIMEOUT))){
- return false;
- }
- }
-
- boost::this_thread::sleep(boost::posix_time::milliseconds(100));
- }
-
- return true;
- }
-
- void _update_stream_args(const ::uhd::stream_args_t &stream_args_)
- {
- ::uhd::stream_args_t stream_args(stream_args_);
- if (stream_args.channels.empty()) {
- stream_args.channels = _stream_args.channels;
- }
- if (stream_args.cpu_format != _stream_args.cpu_format ||
- stream_args.channels.size() != _stream_args.channels.size()) {
- throw std::runtime_error("Cannot change I/O signatures while updating stream args!");
- }
- _stream_args = stream_args;
- }
-
- //! Shared pointer to the underlying multi_usrp object
- ::uhd::usrp::multi_usrp::sptr _dev;
- ::uhd::stream_args_t _stream_args;
- boost::shared_ptr< ::uhd::io_type_t > _type;
- //! Number of channels (i.e. number of in- or outputs)
- size_t _nchan;
- bool _stream_now;
- ::uhd::time_spec_t _start_time;
- bool _start_time_set;
- };
-
- } /* namespace uhd */
-} /* namespace gr */
-
-#endif /* INCLUDED_GR_UHD_USRP_COMMON_H */
-
diff --git a/gr-uhd/lib/usrp_sink_impl.cc b/gr-uhd/lib/usrp_sink_impl.cc
index 08896a8bb0..8f2d2ad4a3 100644
--- a/gr-uhd/lib/usrp_sink_impl.cc
+++ b/gr-uhd/lib/usrp_sink_impl.cc
@@ -64,53 +64,16 @@ namespace gr {
usrp_sink_impl::usrp_sink_impl(const ::uhd::device_addr_t &device_addr,
const ::uhd::stream_args_t &stream_args,
const std::string &length_tag_name)
- : sync_block("gr uhd usrp sink",
+ : usrp_block("gr uhd usrp sink",
args_to_io_sig(stream_args),
io_signature::make(0, 0, 0)),
- usrp_common_impl(device_addr, stream_args, length_tag_name),
+ usrp_block_impl(device_addr, stream_args, length_tag_name),
_length_tag_key(length_tag_name.empty() ? pmt::PMT_NIL : pmt::string_to_symbol(length_tag_name)),
- _nitems_to_send(0),
- _curr_freq(stream_args.channels.size(), 0.0),
- _curr_lo_offset(stream_args.channels.size(), 0.0),
- _curr_gain(stream_args.channels.size(), 0.0),
- _chans_to_tune(stream_args.channels.size())
+ _nitems_to_send(0)
{
- message_port_register_in(pmt::mp("command"));
- set_msg_handler(
- pmt::mp("command"),
- boost::bind(&usrp_sink_impl::msg_handler_command, this, _1)
- );
-
- _check_sensors_locked();
+ _sample_rate = get_samp_rate();
}
- bool usrp_sink_impl::_check_sensors_locked()
- {
- bool clocks_locked = true;
-
- // Check ref lock for all mboards
- for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) {
- std::string sensor_name = "ref_locked";
- if (_dev->get_clock_source(mboard_index) == "internal") {
- continue;
- }
- else if (_dev->get_clock_source(mboard_index) == "mimo") {
- sensor_name = "mimo_locked";
- }
- if (not _wait_for_locked_sensor(
- get_mboard_sensor_names(mboard_index),
- sensor_name,
- boost::bind(&usrp_sink_impl::get_mboard_sensor, this, _1, mboard_index)
- )) {
- GR_LOG_WARN(d_logger, boost::format("Sensor '%s' failed to lock within timeout on motherboard %d.") % sensor_name % mboard_index);
- clocks_locked = false;
- }
- }
-
- return clocks_locked;
- }
-
-
usrp_sink_impl::~usrp_sink_impl()
{
}
@@ -169,39 +132,12 @@ namespace gr {
usrp_sink_impl::set_center_freq(const ::uhd::tune_request_t tune_request,
size_t chan)
{
- _curr_freq[chan] = tune_request.target_freq;
- if (tune_request.rf_freq_policy == ::uhd::tune_request_t::POLICY_MANUAL) {
- _curr_lo_offset[chan] = tune_request.rf_freq - tune_request.target_freq;
- } else {
- _curr_lo_offset[chan] = 0.0;
- }
+ _curr_tune_req[chan] = tune_request;
chan = _stream_args.channels[chan];
return _dev->set_tx_freq(tune_request, chan);
}
- ::uhd::tune_result_t
- usrp_sink_impl::_set_center_freq_from_internals(size_t chan)
- {
- _chans_to_tune[chan] = false;
- if (_curr_lo_offset[chan] == 0.0) {
- return _dev->set_tx_freq(_curr_freq[chan], _stream_args.channels[chan]);
- } else {
- return _dev->set_tx_freq(
- ::uhd::tune_request_t(_curr_freq[chan], _curr_lo_offset[chan]),
- _stream_args.channels[chan]
- );
- }
- }
-
- void
- usrp_sink_impl::_set_center_freq_from_internals_allchans()
- {
- for (size_t chan = 0; chan < _nchan; chan++) {
- if (_chans_to_tune[chan]) {
- _set_center_freq_from_internals(chan);
- }
- }
- }
+ SET_CENTER_FREQ_FROM_INTERNALS(usrp_sink_impl, set_tx_freq);
double
usrp_sink_impl::get_center_freq(size_t chan)
@@ -220,7 +156,6 @@ namespace gr {
void
usrp_sink_impl::set_gain(double gain, size_t chan)
{
- _curr_gain[chan] = gain;
chan = _stream_args.channels[chan];
return _dev->set_tx_gain(gain, chan);
}
@@ -230,7 +165,6 @@ namespace gr {
const std::string &name,
size_t chan)
{
- _curr_gain[chan] = gain;
chan = _stream_args.channels[chan];
return _dev->set_tx_gain(gain, name, chan);
}
@@ -375,152 +309,6 @@ namespace gr {
return _dev->get_tx_sensor_names(chan);
}
- ::uhd::sensor_value_t
- usrp_sink_impl::get_mboard_sensor(const std::string &name,
- size_t mboard)
- {
- return _dev->get_mboard_sensor(name, mboard);
- }
-
- std::vector<std::string>
- usrp_sink_impl::get_mboard_sensor_names(size_t mboard)
- {
- return _dev->get_mboard_sensor_names(mboard);
- }
-
- void
- usrp_sink_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
- size_t mboard)
- {
- return _dev->set_clock_config(clock_config, mboard);
- }
-
- void
- usrp_sink_impl::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
- usrp_sink_impl::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>
- usrp_sink_impl::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
- usrp_sink_impl::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
- usrp_sink_impl::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>
- usrp_sink_impl::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
- usrp_sink_impl::get_clock_rate(size_t mboard)
- {
- return _dev->get_master_clock_rate(mboard);
- }
-
- void
- usrp_sink_impl::set_clock_rate(double rate, size_t mboard)
- {
- return _dev->set_master_clock_rate(rate, mboard);
- }
-
- ::uhd::time_spec_t
- usrp_sink_impl::get_time_now(size_t mboard)
- {
- return _dev->get_time_now(mboard);
- }
-
- ::uhd::time_spec_t
- usrp_sink_impl::get_time_last_pps(size_t mboard)
- {
- return _dev->get_time_last_pps(mboard);
- }
-
- void
- usrp_sink_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
- size_t mboard)
- {
- return _dev->set_time_now(time_spec, mboard);
- }
-
- void
- usrp_sink_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_next_pps(time_spec);
- }
-
- void
- usrp_sink_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_unknown_pps(time_spec);
- }
-
- void
- usrp_sink_impl::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
- usrp_sink_impl::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
usrp_sink_impl::get_dboard_iface(size_t chan)
{
@@ -528,24 +316,6 @@ namespace gr {
return _dev->get_tx_dboard_iface(chan);
}
- ::uhd::usrp::multi_usrp::sptr
- usrp_sink_impl::get_device(void)
- {
- return _dev;
- }
-
- void
- usrp_sink_impl::set_user_register(const uint8_t addr,
- const uint32_t data,
- size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
- _dev->set_user_register(addr, data, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
void
usrp_sink_impl::set_stream_args(const ::uhd::stream_args_t &stream_args)
{
@@ -644,7 +414,7 @@ namespace gr {
// Go through tag list until something indicates the end of a burst.
bool found_time_tag = false;
bool found_eob = false;
- // For commands that are in the middle in the burst:
+ // For commands that are in the middle of the burst:
std::vector<pmt::pmt_t> commands_in_burst; // Store the command
uint64_t in_burst_cmd_offset = 0; // Store its position
BOOST_FOREACH(const tag_t &my_tag, _tags) {
@@ -660,7 +430,7 @@ namespace gr {
*
* This includes:
* - tx_time
- * - tx_command
+ * - tx_command TODO should also work end-of-burst
* - tx_sob
* - length tags
*
@@ -672,6 +442,7 @@ namespace gr {
max_count = my_tag_count;
break;
}
+ // TODO set the command time from the sample time
msg_handler_command(value);
}
@@ -727,12 +498,16 @@ namespace gr {
else if (pmt::equal(key, FREQ_KEY) && my_tag_count == samp0_count) {
// If it's on the first sample, immediately do the tune:
GR_LOG_DEBUG(d_debug_logger, boost::format("Received tx_freq on start of burst."));
- msg_handler_command(pmt::cons(pmt::mp("freq"), value));
+ pmt::pmt_t freq_cmd = pmt::make_dict();
+ freq_cmd = pmt::dict_add(freq_cmd, pmt::mp("freq"), value);
+ msg_handler_command(freq_cmd);
}
else if(pmt::equal(key, FREQ_KEY)) {
// If it's not on the first sample, queue this command and only tx until here:
GR_LOG_DEBUG(d_debug_logger, boost::format("Received tx_freq mid-burst."));
- commands_in_burst.push_back(pmt::cons(pmt::mp("freq"), value));
+ pmt::pmt_t freq_cmd = pmt::make_dict();
+ freq_cmd = pmt::dict_add(freq_cmd, pmt::mp("freq"), value);
+ commands_in_burst.push_back(freq_cmd);
max_count = my_tag_count + 1;
in_burst_cmd_offset = my_tag_count;
}
@@ -763,7 +538,7 @@ namespace gr {
// until before the tag, so it will be on the first sample of the next run.
if (not commands_in_burst.empty()) {
if (not found_eob) {
- // If it's in the middle of a burst, only send() until before the tag
+ // ...then it's in the middle of a burst, only send() until before the tag
max_count = in_burst_cmd_offset;
} else if (in_burst_cmd_offset < max_count) {
BOOST_FOREACH(const pmt::pmt_t &cmd_pmt, commands_in_burst) {
@@ -843,69 +618,5 @@ namespace gr {
return true;
}
-
- /************** External interfaces (RPC + Message passing) ********************/
- void usrp_sink_impl::msg_handler_command(pmt::pmt_t msg)
- {
- std::string command;
- pmt::pmt_t cmd_value;
- int chan = -1;
- if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
- GR_LOG_ALERT(d_logger, boost::format("Error while unpacking command PMT: %s") % msg);
- return;
- }
- GR_LOG_DEBUG(d_debug_logger, boost::format("Received command: %s") % command);
- try {
- if (command == "freq") {
- _chans_to_tune = _update_vector_from_cmd_val<double>(
- _curr_freq, chan, pmt::to_double(cmd_value), true
- );
- _set_center_freq_from_internals_allchans();
- } else if (command == "lo_offset") {
- _chans_to_tune = _update_vector_from_cmd_val<double>(
- _curr_lo_offset, chan, pmt::to_double(cmd_value), true
- );
- _set_center_freq_from_internals_allchans();
- } else if (command == "gain") {
- boost::dynamic_bitset<> chans_to_change = _update_vector_from_cmd_val<double>(
- _curr_gain, chan, pmt::to_double(cmd_value), true
- );
- if (chans_to_change.any()) {
- for (size_t i = 0; i < chans_to_change.size(); i++) {
- if (chans_to_change[i]) {
- set_gain(_curr_gain[i], i);
- }
- }
- }
- } else {
- GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % command);
- }
- } catch (pmt::wrong_type &e) {
- GR_LOG_ALERT(d_logger, boost::format("Received command '%s' with invalid command value: %s") % command % cmd_value);
- }
- }
-
- void
- usrp_sink_impl::setup_rpc()
- {
-#ifdef GR_CTRLPORT
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_get<usrp_sink, double>(
- alias(), "samp_rate",
- &usrp_sink::get_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "TX Sample Rate", RPC_PRIVLVL_MIN,
- DISPTIME | DISPOPTSTRIP)));
-
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_set<usrp_sink, double>(
- alias(), "samp_rate",
- &usrp_sink::set_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "TX Sample Rate",
- RPC_PRIVLVL_MIN, DISPNULL)));
-#endif /* GR_CTRLPORT */
- }
-
} /* namespace uhd */
} /* namespace gr */
diff --git a/gr-uhd/lib/usrp_sink_impl.h b/gr-uhd/lib/usrp_sink_impl.h
index e0cb5a9a60..1575378d21 100644
--- a/gr-uhd/lib/usrp_sink_impl.h
+++ b/gr-uhd/lib/usrp_sink_impl.h
@@ -20,9 +20,9 @@
* Boston, MA 02110-1301, USA.
*/
+#include "usrp_block_impl.h"
#include <gnuradio/uhd/usrp_sink.h>
#include <uhd/convert.hpp>
-#include "usrp_common.h"
static const pmt::pmt_t SOB_KEY = pmt::string_to_symbol("tx_sob");
static const pmt::pmt_t EOB_KEY = pmt::string_to_symbol("tx_eob");
@@ -52,7 +52,7 @@ namespace gr {
/***********************************************************************
* UHD Multi USRP Sink Impl
**********************************************************************/
- class usrp_sink_impl : public usrp_sink, public usrp_common_impl
+ class usrp_sink_impl : public usrp_sink, public usrp_block_impl
{
public:
usrp_sink_impl(const ::uhd::device_addr_t &device_addr,
@@ -60,8 +60,6 @@ namespace gr {
const std::string &length_tag_name);
~usrp_sink_impl();
- void setup_rpc();
-
::uhd::dict<std::string, std::string> get_usrp_info(size_t chan);
double get_samp_rate(void);
::uhd::meta_range_t get_samp_rates(void);
@@ -77,17 +75,7 @@ namespace gr {
std::vector<std::string> get_antennas(size_t chan);
::uhd::sensor_value_t get_sensor(const std::string &name, size_t chan);
std::vector<std::string> get_sensor_names(size_t chan);
- ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard);
- std::vector<std::string> get_mboard_sensor_names(size_t mboard);
- std::string get_time_source(const size_t mboard);
- std::vector<std::string> get_time_sources(const size_t mboard);
- std::string get_clock_source(const size_t mboard);
- std::vector<std::string> get_clock_sources(const size_t mboard);
- double get_clock_rate(size_t mboard);
- ::uhd::time_spec_t get_time_now(size_t mboard = 0);
- ::uhd::time_spec_t get_time_last_pps(size_t mboard);
::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan);
- ::uhd::usrp::multi_usrp::sptr get_device(void);
void set_subdev_spec(const std::string &spec, size_t mboard);
std::string get_subdev_spec(size_t mboard);
@@ -103,16 +91,6 @@ namespace gr {
::uhd::freq_range_t get_bandwidth_range(size_t chan);
void set_dc_offset(const std::complex<double> &offset, size_t chan);
void set_iq_balance(const std::complex<double> &correction, size_t chan);
- void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t mboard);
- void set_time_source(const std::string &source, const size_t mboard);
- void set_clock_source(const std::string &source, const size_t mboard);
- void set_clock_rate(double rate, size_t mboard);
- void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
- void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
- void set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void clear_command_time(size_t mboard);
- void set_user_register(const uint8_t addr, const uint32_t data, size_t mboard);
void set_stream_args(const ::uhd::stream_args_t &stream_args);
void set_start_time(const ::uhd::time_spec_t &time);
@@ -126,14 +104,8 @@ namespace gr {
inline void tag_work(int &ninput_items);
private:
- /*! \brief Run through all 'lock' sensors and make sure they are actually locked.
- */
- bool _check_sensors_locked();
-
//! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
::uhd::tune_result_t _set_center_freq_from_internals(size_t chan);
- //! Calls _set_center_freq_from_internals() on all channels
- void _set_center_freq_from_internals_allchans();
#ifdef GR_UHD_USE_STREAM_API
::uhd::tx_streamer::sptr _tx_stream;
@@ -141,27 +113,11 @@ namespace gr {
::uhd::tx_metadata_t _metadata;
double _sample_rate;
-
//stream tags related stuff
std::vector<tag_t> _tags;
const pmt::pmt_t _length_tag_key;
long _nitems_to_send;
- /****** Command interface related **********/
- //! Stores a list of commands for later execution
- std::vector<pmt::pmt_t> _pending_cmds;
- //! Receives commands and handles them
- void msg_handler_command(pmt::pmt_t msg);
- //! Stores the last value we told the USRP to tune to for every channel
- // (this is not necessarily the true value the USRP is currently tuned to!).
- // We could theoretically ask the device, but during streaming, we want to minimize
- // communication with the USRP.
- std::vector<double> _curr_freq;
- //! Stores the last value we told the USRP to have the LO offset for every channel.
- std::vector<double> _curr_lo_offset;
- //! Stores the last gain value we told the USRP to have for every channel.
- std::vector<double> _curr_gain;
- boost::dynamic_bitset<> _chans_to_tune;
};
} /* namespace uhd */
diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc
index 13457402be..6f0283e71f 100644
--- a/gr-uhd/lib/usrp_source_impl.cc
+++ b/gr-uhd/lib/usrp_source_impl.cc
@@ -20,10 +20,8 @@
* Boston, MA 02110-1301, USA.
*/
-#include "usrp_common.h"
#include "usrp_source_impl.h"
#include "gr_uhd_common.h"
-#include <gnuradio/io_signature.h>
#include <boost/format.hpp>
#include <boost/thread/thread.hpp>
#include <boost/make_shared.hpp>
@@ -64,49 +62,21 @@ namespace gr {
usrp_source_impl::usrp_source_impl(const ::uhd::device_addr_t &device_addr,
const ::uhd::stream_args_t &stream_args):
- sync_block("gr uhd usrp source",
+ usrp_block("gr uhd usrp source",
io_signature::make(0, 0, 0),
args_to_io_sig(stream_args)),
- usrp_common_impl(device_addr, stream_args, ""),
+ usrp_block_impl(device_addr, stream_args, ""),
_tag_now(false)
{
std::stringstream str;
str << name() << unique_id();
_id = pmt::string_to_symbol(str.str());
- message_port_register_in(pmt::mp("command"));
- set_msg_handler(
- pmt::mp("command"),
- boost::bind(&usrp_source_impl::msg_handler_command, this, _1)
- );
-
- _check_sensors_locked();
- }
-
- bool usrp_source_impl::_check_sensors_locked()
- {
- bool clocks_locked = true;
-
- // Check ref lock for all mboards
- for (size_t mboard_index = 0; mboard_index < _dev->get_num_mboards(); mboard_index++) {
- std::string sensor_name = "ref_locked";
- if (_dev->get_clock_source(mboard_index) == "internal") {
- continue;
- }
- else if (_dev->get_clock_source(mboard_index) == "mimo") {
- sensor_name = "mimo_locked";
- }
- if (not _wait_for_locked_sensor(
- get_mboard_sensor_names(mboard_index),
- sensor_name,
- boost::bind(&usrp_source_impl::get_mboard_sensor, this, _1, mboard_index)
- )) {
- GR_LOG_WARN(d_logger, boost::format("Sensor '%s' failed to lock within timeout on motherboard %d.") % sensor_name % mboard_index);
- clocks_locked = false;
- }
- }
-
- return clocks_locked;
+ _samp_rate = this->get_samp_rate();
+ _center_freq = this->get_center_freq(0);
+#ifdef GR_UHD_USE_STREAM_API
+ _samps_per_packet = 1;
+#endif
}
usrp_source_impl::~usrp_source_impl()
@@ -175,6 +145,8 @@ namespace gr {
return res;
}
+ SET_CENTER_FREQ_FROM_INTERNALS(usrp_source_impl, set_rx_freq);
+
double
usrp_source_impl::get_center_freq(size_t chan)
{
@@ -364,150 +336,6 @@ namespace gr {
return _dev->get_rx_sensor_names(chan);
}
- ::uhd::sensor_value_t
- usrp_source_impl::get_mboard_sensor(const std::string &name, size_t mboard)
- {
- return _dev->get_mboard_sensor(name, mboard);
- }
-
- std::vector<std::string>
- usrp_source_impl::get_mboard_sensor_names(size_t mboard)
- {
- return _dev->get_mboard_sensor_names(mboard);
- }
-
- void
- usrp_source_impl::set_clock_config(const ::uhd::clock_config_t &clock_config,
- size_t mboard)
- {
- return _dev->set_clock_config(clock_config, mboard);
- }
-
- void
- usrp_source_impl::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
- usrp_source_impl::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>
- usrp_source_impl::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
- usrp_source_impl::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
- usrp_source_impl::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>
- usrp_source_impl::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
- usrp_source_impl::get_clock_rate(size_t mboard)
- {
- return _dev->get_master_clock_rate(mboard);
- }
-
- void
- usrp_source_impl::set_clock_rate(double rate, size_t mboard)
- {
- return _dev->set_master_clock_rate(rate, mboard);
- }
-
- ::uhd::time_spec_t
- usrp_source_impl::get_time_now(size_t mboard)
- {
- return _dev->get_time_now(mboard);
- }
-
- ::uhd::time_spec_t
- usrp_source_impl::get_time_last_pps(size_t mboard)
- {
- return _dev->get_time_last_pps(mboard);
- }
-
- void
- usrp_source_impl::set_time_now(const ::uhd::time_spec_t &time_spec,
- size_t mboard)
- {
- return _dev->set_time_now(time_spec, mboard);
- }
-
- void
- usrp_source_impl::set_time_next_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_next_pps(time_spec);
- }
-
- void
- usrp_source_impl::set_time_unknown_pps(const ::uhd::time_spec_t &time_spec)
- {
- return _dev->set_time_unknown_pps(time_spec);
- }
-
- void
- usrp_source_impl::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
- usrp_source_impl::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
usrp_source_impl::get_dboard_iface(size_t chan)
{
@@ -515,24 +343,6 @@ namespace gr {
return _dev->get_rx_dboard_iface(chan);
}
- ::uhd::usrp::multi_usrp::sptr
- usrp_source_impl::get_device(void)
- {
- return _dev;
- }
-
- void
- usrp_source_impl::set_user_register(const uint8_t addr,
- const uint32_t data,
- size_t mboard)
- {
-#ifdef UHD_USRP_MULTI_USRP_USER_REGS_API
- _dev->set_user_register(addr, data, mboard);
-#else
- throw std::runtime_error("not implemented in this version");
-#endif
- }
-
void
usrp_source_impl::set_stream_args(const ::uhd::stream_args_t &stream_args)
{
@@ -743,59 +553,5 @@ namespace gr {
return num_samps;
}
-
- /************** External interfaces (RPC + Message passing) ********************/
- void usrp_source_impl::msg_handler_command(pmt::pmt_t msg)
- {
- std::string command;
- pmt::pmt_t cmd_value;
- int chan = -1;
- if (not _unpack_chan_command(command, cmd_value, chan, msg)) {
- GR_LOG_ALERT(d_logger, "Error while unpacking command PMT.");
- }
- if (command == "freq") {
- double freq = pmt::to_double(cmd_value);
- for (size_t i = 0; i < _nchan; i++) {
- if (chan == -1 || chan == int(i)) {
- set_center_freq(freq, i);
- }
- }
- // TODO: implement
- //} else if (command == "lo_offset") {
- //;
- } else if (command == "gain") {
- double gain = pmt::to_double(cmd_value);
- for (size_t i = 0; i < _nchan; i++) {
- if (chan == -1 || chan == int(i)) {
- set_gain(gain, i);
- }
- }
- } else {
- GR_LOG_ALERT(d_logger, boost::format("Received unknown command: %s") % command);
- }
- }
-
- void
- usrp_source_impl::setup_rpc()
- {
-#ifdef GR_CTRLPORT
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_get<usrp_source, double>(
- alias(), "samp_rate",
- &usrp_source::get_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "RX Sample Rate", RPC_PRIVLVL_MIN,
- DISPTIME | DISPOPTSTRIP)));
-
- add_rpc_variable(
- rpcbasic_sptr(new rpcbasic_register_set<usrp_source, double>(
- alias(), "samp_rate",
- &usrp_source::set_samp_rate,
- pmt::mp(100000.0f), pmt::mp(25000000.0f), pmt::mp(1000000.0f),
- "sps", "RX Sample Rate",
- RPC_PRIVLVL_MIN, DISPNULL)));
-#endif /* GR_CTRLPORT */
- }
-
} /* namespace uhd */
} /* namespace gr */
diff --git a/gr-uhd/lib/usrp_source_impl.h b/gr-uhd/lib/usrp_source_impl.h
index 0cbbe2b16b..9f6fc1a759 100644
--- a/gr-uhd/lib/usrp_source_impl.h
+++ b/gr-uhd/lib/usrp_source_impl.h
@@ -20,10 +20,10 @@
* Boston, MA 02110-1301, USA.
*/
+#include "usrp_block_impl.h"
#include <gnuradio/uhd/usrp_source.h>
#include <uhd/convert.hpp>
#include <boost/thread/mutex.hpp>
-#include "usrp_common.h"
static const pmt::pmt_t TIME_KEY = pmt::string_to_symbol("rx_time");
static const pmt::pmt_t RATE_KEY = pmt::string_to_symbol("rx_rate");
@@ -51,15 +51,13 @@ namespace gr {
/***********************************************************************
* UHD Multi USRP Source Impl
**********************************************************************/
- class usrp_source_impl : public usrp_source, public usrp_common_impl
+ class usrp_source_impl : public usrp_source, public usrp_block_impl
{
public:
usrp_source_impl(const ::uhd::device_addr_t &device_addr,
const ::uhd::stream_args_t &stream_args);
~usrp_source_impl();
- void setup_rpc();
-
// Get Commands
::uhd::dict<std::string, std::string> get_usrp_info(size_t chan);
std::string get_subdev_spec(size_t mboard);
@@ -77,17 +75,7 @@ namespace gr {
std::vector<std::string> get_antennas(size_t chan);
::uhd::sensor_value_t get_sensor(const std::string &name, size_t chan);
std::vector<std::string> get_sensor_names(size_t chan);
- ::uhd::sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard);
- std::vector<std::string> get_mboard_sensor_names(size_t mboard);
- std::string get_time_source(const size_t mboard);
- std::vector<std::string> get_time_sources(const size_t mboard);
- std::string get_clock_source(const size_t mboard);
- std::vector<std::string> get_clock_sources(const size_t mboard);
- double get_clock_rate(size_t mboard);
- ::uhd::time_spec_t get_time_now(size_t mboard = 0);
- ::uhd::time_spec_t get_time_last_pps(size_t mboard);
::uhd::usrp::dboard_iface::sptr get_dboard_iface(size_t chan);
- ::uhd::usrp::multi_usrp::sptr get_device(void);
// Set Commands
void set_subdev_spec(const std::string &spec, size_t mboard);
@@ -105,20 +93,10 @@ namespace gr {
void set_dc_offset(const std::complex<double> &offset, size_t chan);
void set_auto_iq_balance(const bool enable, size_t chan);
void set_iq_balance(const std::complex<double> &correction, size_t chan);
- void set_clock_config(const ::uhd::clock_config_t &clock_config, size_t mboard);
- void set_time_source(const std::string &source, const size_t mboard);
- void set_clock_source(const std::string &source, const size_t mboard);
- void set_clock_rate(double rate, size_t mboard);
- void set_time_now(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void set_time_next_pps(const ::uhd::time_spec_t &time_spec);
- void set_time_unknown_pps(const ::uhd::time_spec_t &time_spec);
- void set_command_time(const ::uhd::time_spec_t &time_spec, size_t mboard);
- void set_user_register(const uint8_t addr, const uint32_t data, size_t mboard);
void set_stream_args(const ::uhd::stream_args_t &stream_args);
void set_start_time(const ::uhd::time_spec_t &time);
void issue_stream_cmd(const ::uhd::stream_cmd_t &cmd);
- void clear_command_time(size_t mboard);
void flush(void);
bool start(void);
bool stop(void);
@@ -129,9 +107,9 @@ namespace gr {
gr_vector_void_star &output_items);
private:
- /*! \brief Run through all 'lock' sensors and make sure they are actually locked.
- */
- bool _check_sensors_locked();
+ //! Like set_center_freq(), but uses _curr_freq and _curr_lo_offset
+ ::uhd::tune_result_t _set_center_freq_from_internals(size_t chan);
+
#ifdef GR_UHD_USE_STREAM_API
::uhd::rx_streamer::sptr _rx_stream;
size_t _samps_per_packet;
@@ -145,21 +123,6 @@ namespace gr {
double _center_freq;
boost::recursive_mutex d_mutex;
-
- /****** Command interface related **********/
- //! Receives commands and handles them
- void msg_handler_command(pmt::pmt_t msg);
- //! Stores the last value we told the USRP to tune to for every channel
- // (this is not necessarily the true value the USRP is currently tuned to!).
- // We could theoretically ask the device, but during streaming, we want to minimize
- // communication with the USRP.
- std::vector<double> _curr_freq;
- //! Stores the last value we told the USRP to have the LO offset for every channel.
- std::vector<double> _curr_lo_offset;
- //! Stores the last gain value we told the USRP to have for every channel.
- std::vector<double> _curr_gain;
- boost::dynamic_bitset<> _chans_to_tune;
- bool _call_tune;
};
} /* namespace uhd */
diff --git a/gr-uhd/swig/uhd_swig.i b/gr-uhd/swig/uhd_swig.i
index a4b1528439..108f544da3 100644
--- a/gr-uhd/swig/uhd_swig.i
+++ b/gr-uhd/swig/uhd_swig.i
@@ -54,6 +54,8 @@
#include <gnuradio/uhd/amsg_source.h>
%}
+%include "gnuradio/uhd/usrp_block.h"
+
////////////////////////////////////////////////////////////////////////
// used types
////////////////////////////////////////////////////////////////////////
diff --git a/grc/base/Block.py b/grc/base/Block.py
index afe326bbf4..5e8a7179ac 100644
--- a/grc/base/Block.py
+++ b/grc/base/Block.py
@@ -19,12 +19,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from . import odict
from . Constants import ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB
+from . Constants import BLOCK_FLAG_THROTTLE, BLOCK_FLAG_DISABLE_BYPASS
+from . Constants import BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED
from Element import Element
from Cheetah.Template import Template
from UserDict import UserDict
from itertools import imap
+from .. gui import Messages
+
+
class TemplateArg(UserDict):
"""
A cheetah template argument created from a param.
@@ -46,11 +51,16 @@ class TemplateArg(UserDict):
def __call__(self):
return self._param.get_evaluated()
-def _get_keys(lst): return [elem.get_key() for elem in lst]
+
+def _get_keys(lst):
+ return [elem.get_key() for elem in lst]
+
+
def _get_elem(lst, key):
try: return lst[_get_keys(lst).index(key)]
except ValueError: raise ValueError, 'Key "%s" not found in %s.'%(key, _get_keys(lst))
+
class Block(Element):
def __init__(self, flow_graph, n):
@@ -73,6 +83,10 @@ class Block(Element):
self._name = n.find('name')
self._key = n.find('key')
self._category = n.find('category') or ''
+ self._flags = n.find('flags') or ''
+ # Backwards compatibility
+ if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags:
+ self._flags += BLOCK_FLAG_THROTTLE
self._grc_source = n.find('grc_source') or ''
self._block_wrapper_path = n.find('block_wrapper_path')
self._bussify_sink = n.find('bus_sink')
@@ -143,6 +157,10 @@ class Block(Element):
and (self._key != "pad_sink"))
is_variable = self._key.startswith('variable')
+ # Disable blocks that are virtual/pads or variables
+ if not is_not_virtual_or_pad or is_variable:
+ self._flags += BLOCK_FLAG_DISABLE_BYPASS
+
if is_not_virtual_or_pad and not is_variable:
self.get_params().append(self.get_parent().get_parent().Param(
block=self,
@@ -197,7 +215,6 @@ class Block(Element):
})
))
-
def back_ofthe_bus(self, portlist):
portlist.sort(key=lambda p: p._type == 'bus')
@@ -205,6 +222,35 @@ class Block(Element):
buslist = [p for p in ports if p._type == 'bus']
return buslist or ports
+ # Main functions to get and set the block state
+ # Also kept get_enabled and set_enabled to keep compatibility
+ def get_state(self):
+ """
+ Gets the block's current state.
+
+ Returns:
+ ENABLED - 0
+ BYPASSED - 1
+ DISABLED - 2
+ """
+ try: return int(eval(self.get_param('_enabled').get_value()))
+ except: return BLOCK_ENABLED
+
+ def set_state(self, state):
+ """
+ Sets the state for the block.
+
+ Args:
+ ENABLED - 0
+ BYPASSED - 1
+ DISABLED - 2
+ """
+ if state in [BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED]:
+ self.get_param('_enabled').set_value(str(state))
+ else:
+ self.get_param('_enabled').set_value(str(BLOCK_ENABLED))
+
+ # Enable/Disable Aliases
def get_enabled(self):
"""
Get the enabled state of the block.
@@ -212,8 +258,7 @@ class Block(Element):
Returns:
true for enabled
"""
- try: return eval(self.get_param('_enabled').get_value())
- except: return True
+ return not (self.get_state() == BLOCK_DISABLED)
def set_enabled(self, enabled):
"""
@@ -221,8 +266,45 @@ class Block(Element):
Args:
enabled: true for enabled
+
+ Returns:
+ True if block changed state
+ """
+ old_state = self.get_state()
+ new_state = BLOCK_ENABLED if enabled else BLOCK_DISABLED
+ self.set_state(new_state)
+ return old_state != new_state
+
+ # Block bypassing
+ def get_bypassed(self):
+ """
+ Check if the block is bypassed
"""
- self.get_param('_enabled').set_value(str(enabled))
+ return self.get_state() == BLOCK_BYPASSED
+
+ def set_bypassed(self):
+ """
+ Bypass the block
+
+ Returns:
+ True if block chagnes state
+ """
+ if self.get_state() != BLOCK_BYPASSED and self.can_bypass():
+ self.set_state(BLOCK_BYPASSED)
+ return True
+ return False
+
+ def can_bypass(self):
+ """ Check the number of sinks and sources and see if this block can be bypassed """
+ # Check to make sure this is a single path block
+ # Could possibly support 1 to many blocks
+ if len(self.get_sources()) != 1 or len(self.get_sinks()) != 1:
+ return False
+ if not (self.get_sources()[0].get_type() == self.get_sinks()[0].get_type()):
+ return False
+ if self.bypass_disabled():
+ return False
+ return True
def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
@@ -240,6 +322,10 @@ class Block(Element):
def get_block_wrapper_path(self): return self._block_wrapper_path
def get_comment(self): return self.get_param('comment').get_value()
+ def get_flags(self): return self._flags
+ def throtteling(self): return BLOCK_FLAG_THROTTLE in self._flags
+ def bypass_disabled(self): return BLOCK_FLAG_DISABLE_BYPASS in self._flags
+
##############################################
# Access Params
##############################################
@@ -414,7 +500,7 @@ class Block(Element):
"""
n = odict()
n['key'] = self.get_key()
- n['param'] = map(lambda p: p.export_data(), self.get_params())
+ n['param'] = map(lambda p: p.export_data(), sorted(self.get_params(), key=str))
if 'bus' in map(lambda a: a.get_type(), self.get_sinks()):
n['bus_sink'] = str(1);
if 'bus' in map(lambda a: a.get_type(), self.get_sources()):
diff --git a/grc/base/Constants.py b/grc/base/Constants.py
index efae0ecbb5..0c5116c604 100644
--- a/grc/base/Constants.py
+++ b/grc/base/Constants.py
@@ -38,3 +38,11 @@ DOMAIN_DTD = os.path.join(DATA_DIR, 'domain.dtd')
GR_STREAM_DOMAIN = "gr_stream"
GR_MESSAGE_DOMAIN = "gr_message"
DEFAULT_DOMAIN = GR_STREAM_DOMAIN
+
+BLOCK_FLAG_THROTTLE = 'throttle'
+BLOCK_FLAG_DISABLE_BYPASS = 'disable_bypass'
+
+# Block States
+BLOCK_DISABLED = 0
+BLOCK_ENABLED = 1
+BLOCK_BYPASSED = 2
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
index fb25b46821..7fd8df5f64 100644
--- a/grc/base/FlowGraph.py
+++ b/grc/base/FlowGraph.py
@@ -78,9 +78,6 @@ class FlowGraph(Element):
bus_structure = block.form_bus_structure('sink');
if 'bus' in map(lambda a: a.get_type(), get_p_gui()):
-
-
-
if len(get_p_gui()) > len(bus_structure):
times = range(len(bus_structure), len(get_p_gui()));
for i in times:
@@ -100,8 +97,6 @@ class FlowGraph(Element):
port = block.get_parent().get_parent().Port(block=block, n=n, dir=direc);
get_p().append(port);
-
-
for child in self.get_children(): child.rewrite()
refactor_bus_structure();
@@ -126,13 +121,13 @@ class FlowGraph(Element):
def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0]
def get_blocks_unordered(self): return filter(lambda e: e.is_block(), self.get_elements())
def get_blocks(self):
- blocks = self.get_blocks_unordered();
- for i in range(len(blocks)):
- if blocks[i].get_key() == 'variable':
- blk = blocks[i];
- blocks.remove(blk);
- blocks.insert(1, blk);
- return blocks;
+ # refactored the slow, ugly version
+ # don't know why we need this here, using it for sorted export_data()
+ return sorted(self.get_blocks_unordered(), key=lambda b: (
+ b.get_key() != 'options', # options to the front
+ not b.get_key().startswith('variable'), # then vars
+ str(b)
+ ))
def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements())
def get_children(self): return self.get_elements()
def get_elements(self):
@@ -159,6 +154,15 @@ class FlowGraph(Element):
"""
return filter(lambda b: b.get_enabled(), self.get_blocks())
+ def get_bypassed_blocks(self):
+ """
+ Get a list of all blocks that are bypassed.
+
+ Returns:
+ a list of blocks
+ """
+ return filter(lambda b: b.get_bypassed(), self.get_blocks())
+
def get_enabled_connections(self):
"""
Get a list of all connections that are enabled.
@@ -166,7 +170,41 @@ class FlowGraph(Element):
Returns:
a list of connections
"""
- return filter(lambda c: c.get_enabled(), self.get_connections())
+ # First get all the enabled connections, then get the bypassed blocks.
+ connections = filter(lambda c: c.get_enabled(), self.get_connections())
+ bypassed_blocks = self.get_bypassed_blocks()
+
+ # Bypassing blocks: Need to find all the enabled connections for the block using
+ # the *connections* object rather than get_connections(). Create new connections
+ # that bypass the selected block and remove the existing ones. This allows adjacent
+ # bypassed blocks to see the newly created connections to downstream blocks,
+ # allowing them to correctly construct bypass connections.
+
+ for block in bypassed_blocks:
+ # Get the upstream connection (off of the sink ports)
+ # Use *connections* not get_connections()
+ get_source_connection = lambda c: c.get_sink() == block.get_sinks()[0]
+ source_connection = filter(get_source_connection, connections)
+ # The source connection should never have more than one element.
+ assert (len(source_connection) == 1)
+
+ # Get the source of the connection.
+ source_port = source_connection[0].get_source()
+
+ # Loop through all the downstream connections
+ get_sink_connections = lambda c: c.get_source() == block.get_sources()[0]
+ for sink in filter(get_sink_connections, connections):
+ if not sink.get_enabled():
+ # Ignore disabled connections
+ continue
+ sink_port = sink.get_sink()
+ connection = self.get_parent().Connection(flow_graph=self, porta=source_port, portb=sink_port)
+ connections.append(connection)
+ # Remove this sink connection
+ connections.remove(sink)
+ # Remove the source connection
+ connections.remove(source_connection[0])
+ return connections
def get_new_block(self, key):
"""
@@ -250,8 +288,8 @@ class FlowGraph(Element):
"""
n = odict()
n['timestamp'] = self._timestamp
- n['block'] = [block.export_data() for block in self.get_blocks()]
- n['connection'] = [connection.export_data() for connection in self.get_connections()]
+ n['block'] = [b.export_data() for b in self.get_blocks()] # already sorted
+ n['connection'] = [c.export_data() for c in sorted(self.get_connections(), key=str)]
instructions = odict({
'created': self.get_parent().get_version_short(),
'format': FLOW_GRAPH_FILE_FORMAT_VERSION,
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index fee96624bb..1ce4aeda2d 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -29,7 +29,7 @@ import subprocess
import Preferences
from threading import Thread
import Messages
-from .. base import ParseXML
+from .. base import ParseXML, Constants
from MainWindow import MainWindow
from PropsDialog import PropsDialog
from ParserErrorsDialog import ParserErrorsDialog
@@ -171,6 +171,11 @@ class ActionHandler:
self.get_flow_graph().update()
self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
self.get_page().set_saved(False)
+ elif action == Actions.BLOCK_BYPASS:
+ if self.get_flow_graph().bypass_selected():
+ self.get_flow_graph().update()
+ self.get_page().get_state_cache().save_new_state(self.get_flow_graph().export_data())
+ self.get_page().set_saved(False)
##################################################
# Cut/Copy/Paste
##################################################
@@ -553,23 +558,34 @@ class ActionHandler:
##################################################
# Global Actions for all States
##################################################
+ selected_block = self.get_flow_graph().get_selected_block()
+ selected_blocks = self.get_flow_graph().get_selected_blocks()
+
#update general buttons
Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not self.get_flow_graph().is_valid())
Actions.ELEMENT_DELETE.set_sensitive(bool(self.get_flow_graph().get_selected_elements()))
- Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(self.get_flow_graph().get_selected_block()))
- Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_ROTATE_CW.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(selected_block))
+ Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(selected_blocks))
+ Actions.BLOCK_ROTATE_CW.set_sensitive(bool(selected_blocks))
#update cut/copy/paste
- Actions.BLOCK_CUT.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_COPY.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ Actions.BLOCK_CUT.set_sensitive(bool(selected_blocks))
+ Actions.BLOCK_COPY.set_sensitive(bool(selected_blocks))
Actions.BLOCK_PASTE.set_sensitive(bool(self.clipboard))
- #update enable/disable
- Actions.BLOCK_ENABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_DISABLE.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BLOCK_CREATE_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.OPEN_HIER.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BUSSIFY_SOURCES.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
- Actions.BUSSIFY_SINKS.set_sensitive(bool(self.get_flow_graph().get_selected_blocks()))
+ #update enable/disable/bypass
+ can_enable = any(block.get_state() != Constants.BLOCK_ENABLED
+ for block in selected_blocks)
+ can_disable = any(block.get_state() != Constants.BLOCK_DISABLED
+ for block in selected_blocks)
+ can_bypass_all = all(block.can_bypass() for block in selected_blocks) \
+ and any (not block.get_bypassed() for block in selected_blocks)
+ Actions.BLOCK_ENABLE.set_sensitive(can_enable)
+ Actions.BLOCK_DISABLE.set_sensitive(can_disable)
+ Actions.BLOCK_BYPASS.set_sensitive(can_bypass_all)
+
+ Actions.BLOCK_CREATE_HIER.set_sensitive(bool(selected_blocks))
+ Actions.OPEN_HIER.set_sensitive(bool(selected_blocks))
+ Actions.BUSSIFY_SOURCES.set_sensitive(bool(selected_blocks))
+ Actions.BUSSIFY_SINKS.set_sensitive(bool(selected_blocks))
Actions.RELOAD_BLOCKS.set_sensitive(True)
Actions.FIND_BLOCKS.set_sensitive(True)
#set the exec and stop buttons
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index b2b3a76386..a028a33a11 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -247,6 +247,12 @@ BLOCK_DISABLE = Action(
stock_id=gtk.STOCK_DISCONNECT,
keypresses=(gtk.keysyms.d, NO_MODS_MASK),
)
+BLOCK_BYPASS = Action(
+ label='_Bypass',
+ tooltip='Bypass the selected block',
+ stock_id=gtk.STOCK_MEDIA_FORWARD,
+ keypresses=(gtk.keysyms.b, NO_MODS_MASK),
+)
TOGGLE_SNAP_TO_GRID = ToggleAction(
label='_Snap to grid',
tooltip='Snap blocks to a grid for an easier connection alignment',
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index 40ce20536c..abcc3c6434 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -49,6 +49,7 @@ TOOLBAR_LIST = (
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
Actions.TOGGLE_HIDE_DISABLED_BLOCKS,
None,
Actions.FIND_BLOCKS,
@@ -85,6 +86,7 @@ MENU_BAR_LIST = (
None,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
None,
Actions.BLOCK_PARAM_MODIFY,
]),
@@ -134,6 +136,7 @@ CONTEXT_MENU_LIST = [
Actions.BLOCK_ROTATE_CW,
Actions.BLOCK_ENABLE,
Actions.BLOCK_DISABLE,
+ Actions.BLOCK_BYPASS,
None,
(gtk.Action('More', '_More', None, None), [
Actions.BLOCK_CREATE_HIER,
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 60f19fc1a4..83706ed1aa 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -145,7 +145,9 @@ class Block(Element):
"""Create the labels for the signal block."""
Element.create_labels(self)
self._bg_color = self.is_dummy_block() and Colors.MISSING_BLOCK_BACKGROUND_COLOR or \
+ self.get_bypassed() and Colors.BLOCK_BYPASSED_COLOR or \
self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR
+
layouts = list()
#create the main layout
layout = gtk.DrawingArea().create_pango_layout('')
diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py
index f64106b03f..52c95e8edf 100644
--- a/grc/gui/Colors.py
+++ b/grc/gui/Colors.py
@@ -38,6 +38,7 @@ try:
#block color constants
BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
+ BLOCK_BYPASSED_COLOR = get_color('#FFFFE6')
#connection color constants
CONNECTION_ENABLED_COLOR = get_color('black')
CONNECTION_DISABLED_COLOR = get_color('#BBBBBB')
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 97f814f1bf..bf6e1eed78 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -211,9 +211,21 @@ class FlowGraph(Element):
"""
changed = False
for selected_block in self.get_selected_blocks():
- if selected_block.get_enabled() != enable:
- selected_block.set_enabled(enable)
- changed = True
+ if selected_block.set_enabled(enable): changed = True
+ return changed
+
+ def bypass_selected(self):
+ """
+ Bypass the selected blocks.
+
+ Args:
+ None
+ Returns:
+ true if changed
+ """
+ changed = False
+ for selected_block in self.get_selected_blocks():
+ if selected_block.set_bypassed(): changed = True
return changed
def move_selected(self, delta_coordinate):
diff --git a/grc/python/Block.py b/grc/python/Block.py
index 191b03b452..5d52e2bf3c 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -52,7 +52,6 @@ class Block(_Block, _GUIBlock):
self._var_make = n.find('var_make')
self._checks = n.findall('check')
self._callbacks = n.findall('callback')
- self._throttle = n.find('throttle') or ''
self._bus_structure_source = n.find('bus_structure_source') or ''
self._bus_structure_sink = n.find('bus_structure_sink') or ''
#build the block
@@ -78,8 +77,6 @@ class Block(_Block, _GUIBlock):
except: return ''
- def throttle(self): return bool(self._throttle)
-
def validate(self):
"""
Validate this block.
diff --git a/grc/python/Generator.py b/grc/python/Generator.py
index a3f9f10fc1..d9e92cd31f 100644
--- a/grc/python/Generator.py
+++ b/grc/python/Generator.py
@@ -86,7 +86,7 @@ class TopBlockGenerator(object):
def write(self):
"""generate output and write it to files"""
# do throttle warning
- throttling_blocks = filter(lambda b: b.throttle(), self._flow_graph.get_enabled_blocks())
+ throttling_blocks = filter(lambda b: b.throtteling(), self._flow_graph.get_enabled_blocks())
if not throttling_blocks and self._generate_options != 'hb':
Messages.send_warning("This flow graph may not have flow control: "
"no audio or RF hardware blocks found. "
diff --git a/grc/python/block.dtd b/grc/python/block.dtd
index 8cfd3dd392..145f4d8610 100644
--- a/grc/python/block.dtd
+++ b/grc/python/block.dtd
@@ -25,7 +25,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
Top level element.
A block contains a name, ...parameters list, and list of IO ports.
-->
-<!ELEMENT block (name, key, category?, throttle?, import*, var_make?, var_value?, make, callback*, param_tab_order?, param*, bus_sink?, bus_source?, check*, sink*, source*, bus_structure_sink?, bus_structure_source?, doc?, grc_source?)>
+<!ELEMENT block (name, key, category?, throttle?, flags?, import*, var_make?, var_value?,
+ make, callback*, param_tab_order?, param*, bus_sink?, bus_source?, check*,
+ sink*, source*, bus_structure_sink?, bus_structure_source?, doc?, grc_source?)>
<!--
Sub level elements.
-->
@@ -64,3 +66,4 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
<!ELEMENT callback (#PCDATA)>
<!ELEMENT optional (#PCDATA)>
<!ELEMENT throttle (#PCDATA)>
+<!ELEMENT flags (#PCDATA)>
diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion
index 7a407eaaf8..b8b960a91e 100755
--- a/grc/scripts/gnuradio-companion
+++ b/grc/scripts/gnuradio-companion
@@ -55,6 +55,14 @@ def show_gtk_error_dialog(title, message):
d.run()
+def check_gtk_init():
+ try:
+ gtk.init_check()
+ except RuntimeError:
+ print 'GTK initialization failed - bailing'
+ exit(-1)
+
+
def check_gnuradio_import():
try:
from gnuradio import gr
@@ -108,6 +116,7 @@ def main():
if __name__ == '__main__':
+ check_gtk_init()
check_gnuradio_import()
ensure_blocks_path()
main()