summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--cmake/Modules/GrVersion.cmake8
-rw-r--r--docs/exploring-gnuradio/fm_tx.grc4
-rw-r--r--gnuradio-runtime/include/gnuradio/block.h4
-rw-r--r--gnuradio-runtime/include/gnuradio/block_detail.h7
-rw-r--r--gnuradio-runtime/include/gnuradio/buffer.h4
-rw-r--r--gnuradio-runtime/lib/block_detail.cc20
-rw-r--r--gnuradio-runtime/lib/flat_flowgraph.cc13
-rwxr-xr-xgr-analog/examples/fmtest.py3
-rw-r--r--gr-analog/grc/analog_fm_preemph.xml8
-rw-r--r--gr-analog/grc/analog_nbfm_tx.xml8
-rw-r--r--gr-analog/grc/analog_wfm_tx.xml7
-rw-r--r--gr-analog/lib/CMakeLists.txt11
-rw-r--r--gr-analog/lib/frequency_modulator_fc_impl.cc22
-rw-r--r--gr-analog/lib/frequency_modulator_fc_impl.h2
-rw-r--r--gr-analog/lib/sig_source_X_impl.cc.t32
-rw-r--r--gr-analog/lib/sig_source_X_impl.h.t2
-rw-r--r--gr-analog/python/analog/fm_emph.py254
-rw-r--r--gr-analog/python/analog/nbfm_tx.py5
-rw-r--r--gr-analog/python/analog/wfm_tx.py5
-rw-r--r--gr-blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/grc/blks2_error_rate.xml (renamed from grc/blocks/blks2_error_rate.xml)1
-rw-r--r--gr-blocks/grc/blks2_selector.xml (renamed from grc/blocks/blks2_selector.xml)1
-rw-r--r--gr-blocks/grc/blks2_tcp_sink.xml (renamed from grc/blocks/blks2_tcp_sink.xml)1
-rw-r--r--gr-blocks/grc/blks2_tcp_source.xml (renamed from grc/blocks/blks2_tcp_source.xml)1
-rw-r--r--gr-blocks/grc/blks2_valve.xml (renamed from grc/blocks/blks2_valve.xml)1
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml7
-rw-r--r--gr-blocks/grc/blocks_repeat.xml1
-rw-r--r--gr-blocks/grc/xmlrpc_client.xml (renamed from grc/blocks/xmlrpc_client.xml)0
-rw-r--r--gr-blocks/grc/xmlrpc_server.xml (renamed from grc/blocks/xmlrpc_server.xml)0
-rw-r--r--gr-blocks/include/gnuradio/blocks/repeat.h18
-rw-r--r--gr-blocks/include/gnuradio/blocks/vector_sink_X.h.t1
-rw-r--r--gr-blocks/include/gnuradio/blocks/vector_source_X.h.t1
-rw-r--r--gr-blocks/lib/repeat_impl.cc20
-rw-r--r--gr-blocks/lib/repeat_impl.h6
-rw-r--r--gr-blocks/lib/tuntap_pdu_impl.cc33
-rw-r--r--gr-blocks/lib/tuntap_pdu_impl.h1
-rw-r--r--gr-blocks/lib/vector_sink_X_impl.h.t2
-rw-r--r--gr-blocks/lib/vector_source_X_impl.h.t1
-rw-r--r--gr-blocks/python/blocks/qa_block_behavior.py79
-rwxr-xr-xgr-blocks/python/blocks/qa_vector_sink_source.py36
-rw-r--r--gr-blocks/python/grc_gnuradio/CMakeLists.txt (renamed from grc/grc_gnuradio/CMakeLists.txt)8
-rw-r--r--gr-blocks/python/grc_gnuradio/README (renamed from grc/grc_gnuradio/README)0
-rw-r--r--gr-blocks/python/grc_gnuradio/__init__.py (renamed from grc/grc_gnuradio/__init__.py)0
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/__init__.py (renamed from grc/grc_gnuradio/blks2/__init__.py)10
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/error_rate.py (renamed from grc/grc_gnuradio/blks2/error_rate.py)0
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/selector.py (renamed from grc/grc_gnuradio/blks2/selector.py)0
-rw-r--r--gr-blocks/python/grc_gnuradio/blks2/tcp.py (renamed from grc/grc_gnuradio/blks2/tcp.py)0
-rw-r--r--gr-digital/CMakeLists.txt1
-rw-r--r--gr-digital/grc/blks2_packet_decoder.xml (renamed from grc/blocks/blks2_packet_decoder.xml)1
-rw-r--r--gr-digital/grc/blks2_packet_encoder.xml (renamed from grc/blocks/blks2_packet_encoder.xml)1
-rw-r--r--gr-digital/grc/digital_constellation.xml51
-rwxr-xr-xgr-digital/python/digital/qa_correlate_access_code_XX_ts.py90
-rw-r--r--gr-digital/python/grc_gnuradio/CMakeLists.txt (renamed from grc/base/CMakeLists.txt)29
-rw-r--r--gr-digital/python/grc_gnuradio/blks2/packet.py (renamed from grc/grc_gnuradio/blks2/packet.py)0
-rw-r--r--gr-dtv/CMakeLists.txt2
-rw-r--r--gr-dtv/examples/CMakeLists.txt27
-rw-r--r--gr-dtv/examples/README.catv31
-rw-r--r--gr-dtv/examples/README.dvbs26
-rwxr-xr-xgr-dtv/examples/atsc_ctrlport_monitor.py149
-rw-r--r--gr-dtv/examples/catv_tx_64qam.grc2079
-rw-r--r--gr-dtv/examples/dvbs2_tx.grc2256
-rw-r--r--gr-dtv/examples/dvbs_tx.grc2853
-rw-r--r--gr-dtv/grc/CMakeLists.txt7
-rw-r--r--gr-dtv/grc/dtv_block_tree.xml10
-rw-r--r--gr-dtv/grc/dtv_catv_frame_sync_enc_bb.xml26
-rw-r--r--gr-dtv/grc/dtv_catv_randomizer_bb.xml20
-rw-r--r--gr-dtv/grc/dtv_catv_reed_solomon_enc_bb.xml20
-rw-r--r--gr-dtv/grc/dtv_catv_transport_framing_enc_bb.xml20
-rw-r--r--gr-dtv/grc/dtv_catv_trellis_enc_bb.xml20
-rw-r--r--gr-dtv/grc/dtv_dvbs2_modulator_bc.xml22
-rw-r--r--gr-dtv/include/gnuradio/dtv/CMakeLists.txt7
-rw-r--r--gr-dtv/include/gnuradio/dtv/atsc_equalizer.h3
-rw-r--r--gr-dtv/include/gnuradio/dtv/atsc_rs_decoder.h15
-rw-r--r--gr-dtv/include/gnuradio/dtv/atsc_viterbi_decoder.h6
-rw-r--r--gr-dtv/include/gnuradio/dtv/catv_frame_sync_enc_bb.h54
-rw-r--r--gr-dtv/include/gnuradio/dtv/catv_randomizer_bb.h53
-rw-r--r--gr-dtv/include/gnuradio/dtv/catv_reed_solomon_enc_bb.h53
-rw-r--r--gr-dtv/include/gnuradio/dtv/catv_transport_framing_enc_bb.h53
-rw-r--r--gr-dtv/include/gnuradio/dtv/catv_trellis_enc_bb.h53
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbs2_config.h6
-rw-r--r--gr-dtv/include/gnuradio/dtv/dvbs2_modulator_bc.h6
-rw-r--r--gr-dtv/lib/CMakeLists.txt7
-rw-r--r--gr-dtv/lib/atsc/atsc_equalizer_impl.cc89
-rw-r--r--gr-dtv/lib/atsc/atsc_equalizer_impl.h7
-rw-r--r--gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc89
-rw-r--r--gr-dtv/lib/atsc/atsc_rs_decoder_impl.h13
-rw-r--r--gr-dtv/lib/atsc/atsc_single_viterbi.cc65
-rw-r--r--gr-dtv/lib/atsc/atsc_single_viterbi.h17
-rw-r--r--gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc25
-rw-r--r--gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.h4
-rw-r--r--gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.cc96
-rw-r--r--gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.h50
-rw-r--r--gr-dtv/lib/catv/catv_randomizer_bb_impl.cc104
-rw-r--r--gr-dtv/lib/catv/catv_randomizer_bb_impl.h49
-rw-r--r--gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.cc153
-rw-r--r--gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.h56
-rw-r--r--gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.cc131
-rw-r--r--gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.h84
-rw-r--r--gr-dtv/lib/catv/catv_trellis_enc_bb_impl.cc193
-rw-r--r--gr-dtv/lib/catv/catv_trellis_enc_bb_impl.h60
-rw-r--r--gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.cc272
-rw-r--r--gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.h3
-rw-r--r--gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc178
-rw-r--r--gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h21
-rw-r--r--gr-dtv/swig/dtv_swig.i17
-rwxr-xr-xgr-filter/examples/synth_to_chan.py2
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.cc32
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.h6
-rw-r--r--gr-qtgui/grc/qtgui_const_sink_x.xml18
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml35
-rw-r--r--gr-qtgui/grc/qtgui_histogram_sink_x.xml18
-rw-r--r--gr-qtgui/grc/qtgui_time_raster_x.xml17
-rw-r--r--gr-qtgui/grc/qtgui_time_sink_x.xml18
-rw-r--r--gr-qtgui/grc/qtgui_waterfall_sink_x.xml18
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h3
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/const_sink_c.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/displayform.h3
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h2
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h3
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h3
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/histogram_sink_f.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/time_raster_sink_b.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/time_raster_sink_f.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/time_sink_c.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/time_sink_f.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/timecontrolpanel.h2
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h1
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h1
-rw-r--r--gr-qtgui/lib/DisplayPlot.cc9
-rw-r--r--gr-qtgui/lib/FrequencyDisplayPlot.cc13
-rw-r--r--gr-qtgui/lib/WaterfallDisplayPlot.cc2
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.cc6
-rw-r--r--gr-qtgui/lib/const_sink_c_impl.h1
-rw-r--r--gr-qtgui/lib/displayform.cc16
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.cc13
-rw-r--r--gr-qtgui/lib/freq_sink_c_impl.h2
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.cc13
-rw-r--r--gr-qtgui/lib/freq_sink_f_impl.h2
-rw-r--r--gr-qtgui/lib/freqcontrolpanel.cc5
-rw-r--r--gr-qtgui/lib/freqdisplayform.cc6
-rw-r--r--gr-qtgui/lib/histogram_sink_f_impl.cc6
-rw-r--r--gr-qtgui/lib/histogram_sink_f_impl.h1
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.cc6
-rw-r--r--gr-qtgui/lib/time_raster_sink_b_impl.h1
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.cc6
-rw-r--r--gr-qtgui/lib/time_raster_sink_f_impl.h1
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.cc8
-rw-r--r--gr-qtgui/lib/time_sink_c_impl.h1
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.cc6
-rw-r--r--gr-qtgui/lib/time_sink_f_impl.h1
-rw-r--r--gr-qtgui/lib/timecontrolpanel.cc5
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.cc6
-rw-r--r--gr-qtgui/lib/waterfall_sink_c_impl.h1
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.cc6
-rw-r--r--gr-qtgui/lib/waterfall_sink_f_impl.h1
-rw-r--r--gr-uhd/apps/uhd_app.py7
-rwxr-xr-xgr-uhd/examples/python/fm_tx4.py3
-rw-r--r--gr-uhd/include/gnuradio/uhd/usrp_source.h5
-rw-r--r--gr-uhd/lib/usrp_source_impl.cc35
-rw-r--r--gr-uhd/lib/usrp_source_impl.h4
-rw-r--r--gr-utils/python/modtool/gr-newmod/CMakeLists.txt6
-rw-r--r--gr-utils/python/modtool/modtool_add.py14
-rw-r--r--gr-utils/python/modtool/templates.py2
-rw-r--r--grc/CMakeLists.txt10
-rw-r--r--grc/__main__.py20
-rw-r--r--grc/base/Block.py542
-rw-r--r--grc/base/Constants.py50
-rw-r--r--grc/base/FlowGraph.py484
-rw-r--r--grc/base/Param.py205
-rw-r--r--grc/base/Platform.py271
-rw-r--r--grc/base/Port.py136
-rw-r--r--grc/base/__init__.py20
-rw-r--r--grc/blocks/block_tree.xml17
-rwxr-xr-xgrc/checks.py80
-rw-r--r--grc/core/Block.py846
-rw-r--r--grc/core/CMakeLists.txt (renamed from grc/examples/CMakeLists.txt)24
-rw-r--r--grc/core/Config.py55
-rw-r--r--grc/core/Connection.py (renamed from grc/base/Connection.py)83
-rw-r--r--grc/core/Constants.py (renamed from grc/python/Constants.py)85
-rw-r--r--grc/core/Element.py (renamed from grc/base/Element.py)53
-rw-r--r--grc/core/FlowGraph.py594
-rw-r--r--grc/core/Messages.py (renamed from grc/gui/Messages.py)53
-rw-r--r--grc/core/Param.py740
-rw-r--r--grc/core/ParseXML.py (renamed from grc/base/ParseXML.py)22
-rw-r--r--grc/core/Platform.py319
-rw-r--r--grc/core/Port.py404
-rw-r--r--grc/core/__init__.py (renamed from grc/python/__init__.py)0
-rw-r--r--grc/core/block.dtd (renamed from grc/python/block.dtd)0
-rw-r--r--grc/core/block_tree.dtd (renamed from grc/base/block_tree.dtd)0
-rw-r--r--grc/core/default_flow_graph.grc (renamed from grc/python/default_flow_graph.grc)0
-rw-r--r--grc/core/domain.dtd (renamed from grc/base/domain.dtd)0
-rw-r--r--grc/core/flow_graph.dtd (renamed from grc/base/flow_graph.dtd)0
-rw-r--r--grc/core/generator/CMakeLists.txt (renamed from grc/python/CMakeLists.txt)24
-rw-r--r--grc/core/generator/FlowGraphProxy.py126
-rw-r--r--grc/core/generator/Generator.py (renamed from grc/python/Generator.py)195
-rw-r--r--grc/core/generator/__init__.py18
-rw-r--r--grc/core/generator/flow_graph.tmpl (renamed from grc/python/flow_graph.tmpl)9
-rw-r--r--grc/core/utils/CMakeLists.txt26
-rw-r--r--grc/core/utils/__init__.py22
-rw-r--r--grc/core/utils/complexity.py49
-rw-r--r--grc/core/utils/epy_block_io.py (renamed from grc/python/epy_block_io.py)15
-rw-r--r--grc/core/utils/expr_utils.py (renamed from grc/python/expr_utils.py)57
-rw-r--r--grc/core/utils/extract_docs.py (renamed from grc/python/extract_docs.py)47
-rw-r--r--grc/core/utils/odict.py (renamed from grc/base/odict.py)18
-rw-r--r--grc/cpp/README5
-rw-r--r--grc/examples/simple/variable_config.grc561
-rw-r--r--grc/examples/xmlrpc/readme.txt18
-rw-r--r--grc/examples/xmlrpc/xmlrpc_client.grc428
-rw-r--r--grc/examples/xmlrpc/xmlrpc_client_script.py23
-rw-r--r--grc/examples/xmlrpc/xmlrpc_server.grc908
-rw-r--r--grc/gui/ActionHandler.py111
-rw-r--r--grc/gui/Actions.py8
-rw-r--r--grc/gui/Bars.py1
-rw-r--r--grc/gui/Block.py48
-rw-r--r--grc/gui/BlockTreeWindow.py58
-rw-r--r--grc/gui/CMakeLists.txt32
-rw-r--r--grc/gui/Colors.py3
-rw-r--r--grc/gui/Config.py74
-rw-r--r--grc/gui/Connection.py18
-rw-r--r--grc/gui/Constants.py53
-rw-r--r--grc/gui/Dialogs.py33
-rw-r--r--grc/gui/DrawingArea.py27
-rw-r--r--grc/gui/Element.py16
-rw-r--r--grc/gui/Executor.py123
-rw-r--r--grc/gui/FileDialogs.py15
-rw-r--r--grc/gui/FlowGraph.py83
-rw-r--r--grc/gui/MainWindow.py30
-rw-r--r--grc/gui/NotebookPage.py6
-rw-r--r--grc/gui/Param.py15
-rw-r--r--grc/gui/Platform.py53
-rw-r--r--grc/gui/Port.py43
-rw-r--r--grc/gui/Preferences.py6
-rw-r--r--grc/gui/PropsDialog.py38
-rwxr-xr-xgrc/main.py55
-rw-r--r--grc/python/Block.py323
-rw-r--r--grc/python/Connection.py45
-rw-r--r--grc/python/FlowGraph.py338
-rw-r--r--grc/python/Param.py433
-rw-r--r--grc/python/Platform.py174
-rw-r--r--grc/python/Port.py268
-rw-r--r--grc/scripts/CMakeLists.txt2
-rw-r--r--grc/scripts/freedesktop/CMakeLists.txt (renamed from grc/freedesktop/CMakeLists.txt)0
-rw-r--r--grc/scripts/freedesktop/README (renamed from grc/freedesktop/README)0
-rwxr-xr-xgrc/scripts/freedesktop/convert.sh (renamed from grc/freedesktop/convert.sh)0
-rw-r--r--grc/scripts/freedesktop/gnuradio-grc.desktop (renamed from grc/freedesktop/gnuradio-grc.desktop)0
-rw-r--r--grc/scripts/freedesktop/gnuradio-grc.xml (renamed from grc/freedesktop/gnuradio-grc.xml)0
-rw-r--r--grc/scripts/freedesktop/gnuradio_logo_icon-square.svg (renamed from grc/freedesktop/gnuradio_logo_icon-square.svg)0
-rw-r--r--grc/scripts/freedesktop/grc-icon-128.png (renamed from grc/freedesktop/grc-icon-128.png)bin4758 -> 4758 bytes
-rw-r--r--grc/scripts/freedesktop/grc-icon-16.png (renamed from grc/freedesktop/grc-icon-16.png)bin537 -> 537 bytes
-rw-r--r--grc/scripts/freedesktop/grc-icon-24.png (renamed from grc/freedesktop/grc-icon-24.png)bin840 -> 840 bytes
-rw-r--r--grc/scripts/freedesktop/grc-icon-256.png (renamed from grc/freedesktop/grc-icon-256.png)bin9762 -> 9762 bytes
-rw-r--r--grc/scripts/freedesktop/grc-icon-32.png (renamed from grc/freedesktop/grc-icon-32.png)bin1148 -> 1148 bytes
-rw-r--r--grc/scripts/freedesktop/grc-icon-48.png (renamed from grc/freedesktop/grc-icon-48.png)bin1796 -> 1796 bytes
-rw-r--r--grc/scripts/freedesktop/grc-icon-64.png (renamed from grc/freedesktop/grc-icon-64.png)bin2355 -> 2355 bytes
-rw-r--r--grc/scripts/freedesktop/grc_setup_freedesktop.in (renamed from grc/freedesktop/grc_setup_freedesktop.in)0
-rwxr-xr-xgrc/scripts/gnuradio-companion124
-rw-r--r--grc/todo.txt69
260 files changed, 14146 insertions, 7137 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5203e6d4ce..3641ab4b5c 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 9)
-set(VERSION_INFO_MAINT_VERSION 2)
+set(VERSION_INFO_MINOR_VERSION 10)
+set(VERSION_INFO_MAINT_VERSION git)
include(GrVersion) #setup version info
# Append -O2 optimization flag for Debug builds
diff --git a/cmake/Modules/GrVersion.cmake b/cmake/Modules/GrVersion.cmake
index bafd0a7326..dceac67bab 100644
--- a/cmake/Modules/GrVersion.cmake
+++ b/cmake/Modules/GrVersion.cmake
@@ -41,7 +41,13 @@ if(GIT_FOUND AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
else()
- set(GIT_DESCRIBE "v${MAJOR_VERSION}.${API_COMPAT}.x-xxx-xunknown")
+ if(NOT GR_GIT_COUNT)
+ set(GR_GIT_COUNT "compat-xxx")
+ endif()
+ if(NOT GR_GIT_HASH)
+ set(GR_GIT_HASH "xunknown")
+ endif()
+ set(GIT_DESCRIBE "v${MAJOR_VERSION}.${API_COMPAT}-${GR_GIT_COUNT}-${GR_GIT_HASH}")
endif()
########################################################################
diff --git a/docs/exploring-gnuradio/fm_tx.grc b/docs/exploring-gnuradio/fm_tx.grc
index 2f047bf09b..bb13417a6b 100644
--- a/docs/exploring-gnuradio/fm_tx.grc
+++ b/docs/exploring-gnuradio/fm_tx.grc
@@ -792,6 +792,10 @@
<value>75e3</value>
</param>
<param>
+ <key>fh</key>
+ <value>0.925 * tx_rate/2.0</value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
diff --git a/gnuradio-runtime/include/gnuradio/block.h b/gnuradio-runtime/include/gnuradio/block.h
index c6185d9f2d..a484ccf429 100644
--- a/gnuradio-runtime/include/gnuradio/block.h
+++ b/gnuradio-runtime/include/gnuradio/block.h
@@ -80,7 +80,9 @@ namespace gr {
* History is the number of x_i's that are examined to produce one y_i.
* This comes in handy for FIR filters, where we use history to
* ensure that our input contains the appropriate "history" for the
- * filter. History should be equal to the number of filter taps.
+ * filter. History should be equal to the number of filter taps. First
+ * history samples (when there are no previous samples) are
+ * initialized with zeroes.
*/
unsigned history() const;
void set_history(unsigned history);
diff --git a/gnuradio-runtime/include/gnuradio/block_detail.h b/gnuradio-runtime/include/gnuradio/block_detail.h
index 916c0a46c1..a71030b439 100644
--- a/gnuradio-runtime/include/gnuradio/block_detail.h
+++ b/gnuradio-runtime/include/gnuradio/block_detail.h
@@ -100,6 +100,13 @@ namespace gr {
// Return the number of items written on output stream which_output
uint64_t nitems_written(unsigned int which_output);
+ // sets nitems_read and nitems_written to 0 for all input/output
+ // buffers.
+ void reset_nitem_counters();
+
+ // Clears all tags from the input buffers.
+ void clear_tags();
+
/*!
* \brief Adds a new tag to the given output stream.
*
diff --git a/gnuradio-runtime/include/gnuradio/buffer.h b/gnuradio-runtime/include/gnuradio/buffer.h
index 5da383dc8f..914661b318 100644
--- a/gnuradio-runtime/include/gnuradio/buffer.h
+++ b/gnuradio-runtime/include/gnuradio/buffer.h
@@ -100,6 +100,8 @@ namespace gr {
uint64_t nitems_written() { return d_abs_write_offset; }
+ void reset_nitem_counter() { d_abs_write_offset = 0; }
+
size_t get_sizeof_item() { return d_sizeof_item; }
/*!
@@ -288,6 +290,8 @@ namespace gr {
uint64_t nitems_read() { return d_abs_read_offset; }
+ void reset_nitem_counter() { d_abs_read_offset = 0; }
+
size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); }
/*!
diff --git a/gnuradio-runtime/lib/block_detail.cc b/gnuradio-runtime/lib/block_detail.cc
index 9463e8d13b..484d849652 100644
--- a/gnuradio-runtime/lib/block_detail.cc
+++ b/gnuradio-runtime/lib/block_detail.cc
@@ -162,6 +162,26 @@ namespace gr {
}
void
+ block_detail::reset_nitem_counters()
+ {
+ for(unsigned int i = 0; i < d_ninputs; i++) {
+ d_input[i]->reset_nitem_counter();
+ }
+ for(unsigned int o = 0; o < d_noutputs; o++) {
+ d_output[o]->reset_nitem_counter();
+ }
+ }
+
+ void
+ block_detail::clear_tags()
+ {
+ for(unsigned int i = 0; i < d_ninputs; i++) {
+ uint64_t max_time = 0xFFFFFFFFFFFFFFFF; // from now to the end of time
+ d_input[i]->buffer()->prune_tags(max_time);
+ }
+ }
+
+ void
block_detail::add_item_tag(unsigned int which_output, const tag_t &tag)
{
if(!pmt::is_symbol(tag.key)) {
diff --git a/gnuradio-runtime/lib/flat_flowgraph.cc b/gnuradio-runtime/lib/flat_flowgraph.cc
index 81c1184cfa..03e67eb2c2 100644
--- a/gnuradio-runtime/lib/flat_flowgraph.cc
+++ b/gnuradio-runtime/lib/flat_flowgraph.cc
@@ -177,6 +177,13 @@ namespace gr {
catch(std::bad_alloc&) {
b = make_buffer(nitems, item_size, grblock);
}
+
+ // Set the max noutput items size here to make sure it's always
+ // set in the block and available in the start() method.
+ // But don't overwrite if the user has set this externally.
+ if(!grblock->is_set_max_noutput_items())
+ grblock->set_max_noutput_items(nitems);
+
return b;
}
@@ -225,9 +232,10 @@ namespace gr {
std::cout << "merge: allocating new detail for block " << (*p) << std::endl;
block->set_detail(allocate_block_detail(block));
}
- else
+ else {
if(FLAT_FLOWGRAPH_DEBUG)
std::cout << "merge: reusing original detail for block " << (*p) << std::endl;
+ }
}
// Calculate the old edges that will be going away, and clear the
@@ -311,6 +319,9 @@ namespace gr {
// Now deal with the fact that the block details might have
// changed numbers of inputs and outputs vs. in the old
// flowgraph.
+
+ block->detail()->reset_nitem_counters();
+ block->detail()->clear_tags();
}
}
diff --git a/gr-analog/examples/fmtest.py b/gr-analog/examples/fmtest.py
index 327da8eacb..7ed08cafbe 100755
--- a/gr-analog/examples/fmtest.py
+++ b/gr-analog/examples/fmtest.py
@@ -48,7 +48,8 @@ class fmtx(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_float),
gr.io_signature(1, 1, gr.sizeof_gr_complex))
- fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3, tau=75e-6)
+ fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3,
+ tau=75e-6, fh=0.925*if_rate/2.0)
# Local oscillator
lo = analog.sig_source_c(if_rate, # sample rate
diff --git a/gr-analog/grc/analog_fm_preemph.xml b/gr-analog/grc/analog_fm_preemph.xml
index fb898b87f3..a754ce9c6f 100644
--- a/gr-analog/grc/analog_fm_preemph.xml
+++ b/gr-analog/grc/analog_fm_preemph.xml
@@ -8,7 +8,7 @@
<name>FM Preemphasis</name>
<key>analog_fm_preemph</key>
<import>from gnuradio import analog</import>
- <make>analog.fm_preemph(fs=$samp_rate, tau=$tau)</make>
+ <make>analog.fm_preemph(fs=$samp_rate, tau=$tau, fh=$fh)</make>
<param>
<name>Sample Rate</name>
<key>samp_rate</key>
@@ -20,6 +20,12 @@
<value>75e-6</value>
<type>real</type>
</param>
+ <param>
+ <name>High Corner Freq</name>
+ <key>fh</key>
+ <value>-1.0</value>
+ <type>real</type>
+ </param>
<sink>
<name>in</name>
<type>float</type>
diff --git a/gr-analog/grc/analog_nbfm_tx.xml b/gr-analog/grc/analog_nbfm_tx.xml
index ea13b8f1c9..bc80fffbcb 100644
--- a/gr-analog/grc/analog_nbfm_tx.xml
+++ b/gr-analog/grc/analog_nbfm_tx.xml
@@ -13,6 +13,7 @@
quad_rate=$quad_rate,
tau=$tau,
max_dev=$max_dev,
+ fh=$fh,
)</make>
<callback>set_max_deviation($max_dev)</callback>
@@ -42,6 +43,13 @@
<type>real</type>
</param>
+ <param>
+ <name>Preemphasis High Corner Freq</name>
+ <key>fh</key>
+ <value>-1.0</value>
+ <type>real</type>
+ </param>
+
<check>($quad_rate)%($audio_rate) == 0</check>
<sink>
diff --git a/gr-analog/grc/analog_wfm_tx.xml b/gr-analog/grc/analog_wfm_tx.xml
index 89844f9ef3..507c2ea894 100644
--- a/gr-analog/grc/analog_wfm_tx.xml
+++ b/gr-analog/grc/analog_wfm_tx.xml
@@ -13,6 +13,7 @@
quad_rate=$quad_rate,
tau=$tau,
max_dev=$max_dev,
+ fh=$fh,
)</make>
<param>
<name>Audio Rate</name>
@@ -36,6 +37,12 @@
<value>75e3</value>
<type>real</type>
</param>
+ <param>
+ <name>Preemphasis High Corner Freq</name>
+ <key>fh</key>
+ <value>-1.0</value>
+ <type>real</type>
+ </param>
<check>($quad_rate)%($audio_rate) == 0</check>
<sink>
<name>in</name>
diff --git a/gr-analog/lib/CMakeLists.txt b/gr-analog/lib/CMakeLists.txt
index 918f894abe..a75d70337b 100644
--- a/gr-analog/lib/CMakeLists.txt
+++ b/gr-analog/lib/CMakeLists.txt
@@ -110,17 +110,6 @@ GR_LIBRARY_FOO(gnuradio-analog RUNTIME_COMPONENT "analog_runtime" DEVEL_COMPONEN
add_dependencies(gnuradio-analog analog_generated_includes analog_generated_swigs gnuradio-filter)
if(ENABLE_STATIC_LIBS)
- if(ENABLE_GR_CTRLPORT)
- # 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-analog APPEND PROPERTY COMPILE_DEFINITIONS "GR_CTRLPORT")
- endif(ENABLE_GR_CTRLPORT)
-
add_library(gnuradio-analog_static STATIC ${analog_sources})
add_dependencies(gnuradio-analog_static
diff --git a/gr-analog/lib/frequency_modulator_fc_impl.cc b/gr-analog/lib/frequency_modulator_fc_impl.cc
index 812eb8bf0b..56fa0f7c17 100644
--- a/gr-analog/lib/frequency_modulator_fc_impl.cc
+++ b/gr-analog/lib/frequency_modulator_fc_impl.cc
@@ -76,5 +76,27 @@ namespace gr {
return noutput_items;
}
+ void
+ frequency_modulator_fc_impl::setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<frequency_modulator_fc, float>(
+ alias(), "sensitivity",
+ &frequency_modulator_fc::sensitivity,
+ pmt::mp(-1024.0f), pmt::mp(1024.0f), pmt::mp(0.0f),
+ "", "Sensitivity", RPC_PRIVLVL_MIN,
+ DISPTIME | DISPOPTSTRIP)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_set<frequency_modulator_fc, float>(
+ alias(), "sensitivity",
+ &frequency_modulator_fc::set_sensitivity,
+ pmt::mp(-1024.0f), pmt::mp(1024.0f), pmt::mp(0.0f),
+ "", "sensitivity",
+ RPC_PRIVLVL_MIN, DISPNULL)));
+#endif /* GR_CTRLPORT */
+
+ }
} /* namespace analog */
} /* namespace gr */
diff --git a/gr-analog/lib/frequency_modulator_fc_impl.h b/gr-analog/lib/frequency_modulator_fc_impl.h
index 9f5310ce97..9f595d1ddb 100644
--- a/gr-analog/lib/frequency_modulator_fc_impl.h
+++ b/gr-analog/lib/frequency_modulator_fc_impl.h
@@ -41,6 +41,8 @@ namespace gr {
void set_sensitivity(float sens) { d_sensitivity = sens; }
float sensitivity() const { return d_sensitivity; }
+ void setup_rpc();
+
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
diff --git a/gr-analog/lib/sig_source_X_impl.cc.t b/gr-analog/lib/sig_source_X_impl.cc.t
index 227d4ba46e..017177eae0 100644
--- a/gr-analog/lib/sig_source_X_impl.cc.t
+++ b/gr-analog/lib/sig_source_X_impl.cc.t
@@ -53,7 +53,7 @@ namespace gr {
d_frequency(frequency), d_ampl(ampl), d_offset(offset)
{
set_frequency(frequency);
-
+
message_port_register_in(pmt::mp("freq"));
set_msg_handler(pmt::mp("freq"), boost::bind(&@IMPL_NAME@::set_frequency_msg, this, _1));
}
@@ -62,6 +62,36 @@ namespace gr {
{
}
+ void
+ @IMPL_NAME@::set_frequency_msg(pmt::pmt_t msg)
+ {
+ // Accepts either a number that is assumed to be the new
+ // frequency or a key:value pair message where the key must be
+ // "freq" and the value is the new frequency.
+
+ if(pmt::is_number(msg)) {
+ set_frequency(pmt::to_double(msg));
+ }
+ else if(pmt::is_pair(msg)) {
+ pmt::pmt_t key = pmt::car(msg);
+ pmt::pmt_t val = pmt::cdr(msg);
+ if(pmt::eq(key, pmt::intern("freq"))) {
+ if(pmt::is_number(val)) {
+ set_frequency(pmt::to_double(val));
+ }
+ }
+ else {
+ GR_LOG_WARN(d_logger, boost::format("Set Frequency Message must have "
+ "the key = 'freq'; got '%1%'.") \
+ % pmt::write_string(key));
+ }
+ }
+ else {
+ GR_LOG_WARN(d_logger, "Set Frequency Message must be either a number or a "
+ "key:value pair where the key is 'freq'.");
+ }
+ }
+
int
@IMPL_NAME@::work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-analog/lib/sig_source_X_impl.h.t b/gr-analog/lib/sig_source_X_impl.h.t
index bd3609df16..f5dfd5c4f6 100644
--- a/gr-analog/lib/sig_source_X_impl.h.t
+++ b/gr-analog/lib/sig_source_X_impl.h.t
@@ -59,7 +59,7 @@ namespace gr {
void set_sampling_freq(double sampling_freq);
void set_waveform(gr_waveform_t waveform);
- void set_frequency_msg(pmt::pmt_t msg){ set_frequency(pmt::to_double(msg)); };
+ void set_frequency_msg(pmt::pmt_t msg);
void set_frequency(double frequency);
void set_amplitude(double ampl);
void set_offset(@TYPE@ offset);
diff --git a/gr-analog/python/analog/fm_emph.py b/gr-analog/python/analog/fm_emph.py
index d2a38d4aff..bfa4742ace 100644
--- a/gr-analog/python/analog/fm_emph.py
+++ b/gr-analog/python/analog/fm_emph.py
@@ -21,17 +21,78 @@
from gnuradio import gr, filter
import math
+import cmath
#
-# 1
-# H(s) = -------
-# 1 + s
+# An analog deemphasis filter:
#
-# tau is the RC time constant.
-# critical frequency: w_p = 1/tau
+# R
+# o------/\/\/\/---+----o
+# |
+# = C
+# |
+# ---
#
-# We prewarp and use the bilinear z-transform to get our IIR coefficients.
-# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis
+# Has this transfer function:
+#
+# 1 1
+# ---- ---
+# RC tau
+# H(s) = ---------- = ----------
+# 1 1
+# s + ---- s + ---
+# RC tau
+#
+# And has its -3 dB response, due to the pole, at
+#
+# |H(j w_c)|^2 = 1/2 => s = j w_c = j (1/(RC))
+#
+# Historically, this corner frequency of analog audio deemphasis filters
+# been specified by the RC time constant used, called tau.
+# So w_c = 1/tau.
+#
+# FWIW, for standard tau values, some standard analog components would be:
+# tau = 75 us = (50K)(1.5 nF) = (50 ohms)(1.5 uF)
+# tau = 50 us = (50K)(1.0 nF) = (50 ohms)(1.0 uF)
+#
+# In specifying tau for this digital deemphasis filter, tau specifies
+# the *digital* corner frequency, w_c, desired.
+#
+# The digital deemphasis filter design below, uses the
+# "bilinear transformation" method of designing digital filters:
+#
+# 1. Convert digitial specifications into the analog domain, by prewarping
+# digital frequency specifications into analog frequencies.
+#
+# w_a = (2/T)tan(wT/2)
+#
+# 2. Use an analog filter design technique to design the filter.
+#
+# 3. Use the bilinear transformation to convert the analog filter design to a
+# digital filter design.
+#
+# H(z) = H(s)|
+# s = (2/T)(1-z^-1)/(1+z^-1)
+#
+#
+# w_ca 1 1 - (-1) z^-1
+# H(z) = ---- * ----------- * -----------------------
+# 2 fs -w_ca -w_ca
+# 1 - ----- 1 + -----
+# 2 fs 2 fs
+# 1 - ----------- z^-1
+# -w_ca
+# 1 - -----
+# 2 fs
+#
+# We use this design technique, because it is an easy way to obtain a filter
+# design with the -6 dB/octave roll-off required of the deemphasis filter.
+#
+# Jackson, Leland B., _Digital_Filters_and_Signal_Processing_Second_Edition_,
+# Kluwer Academic Publishers, 1989, pp 201-212
+#
+# Orfanidis, Sophocles J., _Introduction_to_Signal_Processing_, Prentice Hall,
+# 1996, pp 573-583
#
@@ -51,15 +112,24 @@ class fm_deemph(gr.hier_block2):
gr.io_signature(1, 1, gr.sizeof_float), # Input signature
gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
- w_p = 1/tau
- w_pp = math.tan(w_p / (fs * 2)) # prewarped analog freq
+ # Digital corner frequency
+ w_c = 1.0 / tau
+
+ # Prewarped analog corner frequency
+ w_ca = 2.0 * fs * math.tan(w_c / (2.0 * fs))
- a1 = (w_pp - 1)/(w_pp + 1)
- b0 = w_pp/(1 + w_pp)
- b1 = b0
+ # Resulting digital pole, zero, and gain term from the bilinear
+ # transformation of H(s) = w_ca / (s + w_ca) to
+ # H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1)
+ k = -w_ca / (2.0 * fs)
+ z1 = -1.0
+ p1 = (1.0 + k) / (1.0 - k)
+ b0 = -k / (1.0 - k)
- btaps = [b0, b1]
- ataps = [1, a1]
+ btaps = [ b0 * 1.0, b0 * -z1 ]
+ ataps = [ 1.0, -p1 ]
+
+ # Since H(s = 0) = 1.0, then H(z = 1) = 1.0 and has 0 dB gain at DC
if 0:
print "btaps =", btaps
@@ -67,26 +137,17 @@ class fm_deemph(gr.hier_block2):
global plot1
plot1 = gru.gnuplot_freqz(gru.freqz(btaps, ataps), fs, True)
- deemph = filter.iir_filter_ffd(btaps, ataps)
+ deemph = filter.iir_filter_ffd(btaps, ataps, False)
self.connect(self, deemph, self)
#
-# 1 + s*t1
-# H(s) = ----------
-# 1 + s*t2
-#
-# I think this is the right transfer function.
-#
+# An analog preemphasis filter, that flattens out again at the high end:
#
-# This fine ASCII rendition is based on Figure 5-15
-# in "Digital and Analog Communication Systems", Leon W. Couch II
-#
-#
-# R1
+# C
# +-----||------+
# | |
# o------+ +-----+--------o
-# | C1 | |
+# | R1 | |
# +----/\/\/\/--+ \
# /
# \ R2
@@ -95,28 +156,94 @@ class fm_deemph(gr.hier_block2):
# |
# o--------------------------+--------o
#
-# f1 = 1/(2*pi*t1) = 1/(2*pi*R1*C)
+# (This fine ASCII rendition is based on Figure 5-15
+# in "Digital and Analog Communication Systems", Leon W. Couch II)
+#
+# Has this transfer function:
#
-# 1 R1 + R2
-# f2 = ------- = ------------
-# 2*pi*t2 2*pi*R1*R2*C
+# 1
+# s + ---
+# R1C
+# H(s) = ------------------
+# 1 R1
+# s + --- (1 + --)
+# R1C R2
#
-# t1 is 75us in US, 50us in EUR
-# f2 should be higher than our audio bandwidth.
#
+# It has a corner due to the numerator, where the rise starts, at
#
-# The Bode plot looks like this:
+# |Hn(j w_cl)|^2 = 2*|Hn(0)|^2 => s = j w_cl = j (1/(R1C))
#
+# It has a corner due to the denominator, where it levels off again, at
#
-# /----------------
-# /
-# / <-- slope = 20dB/decade
-# /
-# -------------/
-# f1 f2
+# |Hn(j w_ch)|^2 = 1/2*|Hd(0)|^2 => s = j w_ch = j (1/(R1C) * (1 + R1/R2))
#
-# We prewarp and use the bilinear z-transform to get our IIR coefficients.
-# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis
+# Historically, the corner frequency of analog audio preemphasis filters
+# been specified by the R1C time constant used, called tau.
+#
+# So
+# w_cl = 1/tau = 1/R1C; f_cl = 1/(2*pi*tau) = 1/(2*pi*R1*C)
+# w_ch = 1/tau2 = (1+R1/R2)/R1C; f_ch = 1/(2*pi*tau2) = (1+R1/R2)/(2*pi*R1*C)
+#
+# and note f_ch = f_cl * (1 + R1/R2).
+#
+# For broadcast FM audio, tau is 75us in the United States and 50us in Europe.
+# f_ch should be higher than our digital audio bandwidth.
+#
+# The Bode plot looks like this:
+#
+#
+# /----------------
+# /
+# / <-- slope = 20dB/decade
+# /
+# -------------/
+# f_cl f_ch
+#
+# In specifying tau for this digital preemphasis filter, tau specifies
+# the *digital* corner frequency, w_cl, desired.
+#
+# The digital preemphasis filter design below, uses the
+# "bilinear transformation" method of designing digital filters:
+#
+# 1. Convert digitial specifications into the analog domain, by prewarping
+# digital frequency specifications into analog frequencies.
+#
+# w_a = (2/T)tan(wT/2)
+#
+# 2. Use an analog filter design technique to design the filter.
+#
+# 3. Use the bilinear transformation to convert the analog filter design to a
+# digital filter design.
+#
+# H(z) = H(s)|
+# s = (2/T)(1-z^-1)/(1+z^-1)
+#
+#
+# -w_cla
+# 1 + ------
+# 2 fs
+# 1 - ------------ z^-1
+# -w_cla -w_cla
+# 1 - ------ 1 - ------
+# 2 fs 2 fs
+# H(z) = ------------ * -----------------------
+# -w_cha -w_cha
+# 1 - ------ 1 + ------
+# 2 fs 2 fs
+# 1 - ------------ z^-1
+# -w_cha
+# 1 - ------
+# 2 fs
+#
+# We use this design technique, because it is an easy way to obtain a filter
+# design with the 6 dB/octave rise required of the premphasis filter.
+#
+# Jackson, Leland B., _Digital_Filters_and_Signal_Processing_Second_Edition_,
+# Kluwer Academic Publishers, 1989, pp 201-212
+#
+# Orfanidis, Sophocles J., _Introduction_to_Signal_Processing_, Prentice Hall,
+# 1996, pp 573-583
#
@@ -124,21 +251,52 @@ class fm_preemph(gr.hier_block2):
"""
FM Preemphasis IIR filter.
"""
- def __init__(self, fs, tau=75e-6):
+ def __init__(self, fs, tau=75e-6, fh=-1.0):
"""
Args:
fs: sampling frequency in Hz (float)
tau: Time constant in seconds (75us in US, 50us in EUR) (float)
+ fh: High frequency at which to flatten out (< 0 means default of 0.925*fs/2.0) (float)
"""
- gr.hier_block2.__init__(self, "fm_deemph",
+ gr.hier_block2.__init__(self, "fm_preemph",
gr.io_signature(1, 1, gr.sizeof_float), # Input signature
gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
- # FIXME make this compute the right answer
+ # Set fh to something sensible, if needed.
+ # N.B. fh == fs/2.0 or fh == 0.0 results in a pole on the unit circle
+ # at z = -1.0 or z = 1.0 respectively. That makes the filter unstable
+ # and useless.
+ if fh <= 0.0 or fh >= fs/2.0:
+ fh = 0.925 * fs/2.0
+
+ # Digital corner frequencies
+ w_cl = 1.0 / tau
+ w_ch = 2.0 * math.pi * fh
+
+ # Prewarped analog corner frequencies
+ w_cla = 2.0 * fs * math.tan(w_cl / (2.0 * fs))
+ w_cha = 2.0 * fs * math.tan(w_ch / (2.0 * fs))
+
+ # Resulting digital pole, zero, and gain term from the bilinear
+ # transformation of H(s) = (s + w_cla) / (s + w_cha) to
+ # H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1)
+ kl = -w_cla / (2.0 * fs)
+ kh = -w_cha / (2.0 * fs)
+ z1 = (1.0 + kl) / (1.0 - kl)
+ p1 = (1.0 + kh) / (1.0 - kh)
+ b0 = (1.0 - kl) / (1.0 - kh)
+
+ # Since H(s = infinity) = 1.0, then H(z = -1) = 1.0 and
+ # this filter has 0 dB gain at fs/2.0.
+ # That isn't what users are going to expect, so adjust with a
+ # gain, g, so that H(z = 1) = 1.0 for 0 dB gain at DC.
+ w_0dB = 2.0 * math.pi * 0.0
+ g = abs(1.0 - p1 * cmath.rect(1.0, -w_0dB)) \
+ / (b0 * abs(1.0 - z1 * cmath.rect(1.0, -w_0dB)))
- btaps = [1]
- ataps = [1]
+ btaps = [ g * b0 * 1.0, g * b0 * -z1 ]
+ ataps = [ 1.0, -p1 ]
if 0:
print "btaps =", btaps
@@ -146,5 +304,5 @@ class fm_preemph(gr.hier_block2):
global plot2
plot2 = gru.gnuplot_freqz(gru.freqz(btaps, ataps), fs, True)
- preemph = filter.iir_filter_ffd(btaps, ataps)
+ preemph = filter.iir_filter_ffd(btaps, ataps, False)
self.connect(self, preemph, self)
diff --git a/gr-analog/python/analog/nbfm_tx.py b/gr-analog/python/analog/nbfm_tx.py
index ffd539ec55..aa6c1eccc7 100644
--- a/gr-analog/python/analog/nbfm_tx.py
+++ b/gr-analog/python/analog/nbfm_tx.py
@@ -29,7 +29,7 @@ except ImportError:
import analog_swig as analog
class nbfm_tx(gr.hier_block2):
- def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3):
+ def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3, fh=-1.0):
"""
Narrow Band FM Transmitter.
@@ -41,6 +41,7 @@ class nbfm_tx(gr.hier_block2):
quad_rate: sample rate of output stream (integer)
tau: preemphasis time constant (default 75e-6) (float)
max_dev: maximum deviation in Hz (default 5e3) (float)
+ fh: high frequency at which to flatten preemphasis; < 0 means default of 0.925*quad_rate/2.0 (float)
quad_rate must be an integer multiple of audio_rate.
"""
@@ -71,7 +72,7 @@ class nbfm_tx(gr.hier_block2):
#print "len(interp_taps) =", len(interp_taps)
self.interpolator = filter.interp_fir_filter_fff (interp_factor, interp_taps)
- self.preemph = fm_preemph(quad_rate, tau=tau)
+ self.preemph = fm_preemph(quad_rate, tau=tau, fh=fh)
k = 2 * math.pi * max_dev / quad_rate
self.modulator = analog.frequency_modulator_fc(k)
diff --git a/gr-analog/python/analog/wfm_tx.py b/gr-analog/python/analog/wfm_tx.py
index be662310db..a1b589350d 100644
--- a/gr-analog/python/analog/wfm_tx.py
+++ b/gr-analog/python/analog/wfm_tx.py
@@ -30,7 +30,7 @@ except ImportError:
import analog_swig as analog
class wfm_tx(gr.hier_block2):
- def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3):
+ def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3, fh=-1.0):
"""
Wide Band FM Transmitter.
@@ -42,6 +42,7 @@ class wfm_tx(gr.hier_block2):
quad_rate: sample rate of output stream (integer)
tau: preemphasis time constant (default 75e-6) (float)
max_dev: maximum deviation in Hz (default 75e3) (float)
+ fh: high frequency at which to flatten preemphasis; < 0 means default of 0.925*quad_rate/2.0 (float)
quad_rate must be an integer multiple of audio_rate.
"""
@@ -71,7 +72,7 @@ class wfm_tx(gr.hier_block2):
print "len(interp_taps) =", len(interp_taps)
self.interpolator = filter.interp_fir_filter_fff (interp_factor, interp_taps)
- self.preemph = fm_preemph(quad_rate, tau=tau)
+ self.preemph = fm_preemph(quad_rate, tau=tau, fh=fh)
k = 2 * math.pi * max_dev / quad_rate
self.modulator = analog.frequency_modulator_fc (k)
diff --git a/gr-blocks/CMakeLists.txt b/gr-blocks/CMakeLists.txt
index 13b41a2e3c..685f5736fb 100644
--- a/gr-blocks/CMakeLists.txt
+++ b/gr-blocks/CMakeLists.txt
@@ -87,6 +87,7 @@ add_subdirectory(lib)
#endif(ENABLE_TESTING)
if(ENABLE_PYTHON)
add_subdirectory(python/blocks)
+ add_subdirectory(python/grc_gnuradio)
add_subdirectory(swig)
add_subdirectory(grc)
add_subdirectory(doc)
diff --git a/grc/blocks/blks2_error_rate.xml b/gr-blocks/grc/blks2_error_rate.xml
index 91a303206d..8be018243f 100644
--- a/grc/blocks/blks2_error_rate.xml
+++ b/gr-blocks/grc/blks2_error_rate.xml
@@ -8,6 +8,7 @@
<block>
<name>Error Rate</name>
<key>blks2_error_rate</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.error_rate(
type=$type,
diff --git a/grc/blocks/blks2_selector.xml b/gr-blocks/grc/blks2_selector.xml
index 2d89df1860..580fdd9d8c 100644
--- a/grc/blocks/blks2_selector.xml
+++ b/gr-blocks/grc/blks2_selector.xml
@@ -8,6 +8,7 @@
<block>
<name>Selector</name>
<key>blks2_selector</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.selector(
item_size=$type.size*$vlen,
diff --git a/grc/blocks/blks2_tcp_sink.xml b/gr-blocks/grc/blks2_tcp_sink.xml
index cfe7b42d84..46b10a7790 100644
--- a/grc/blocks/blks2_tcp_sink.xml
+++ b/gr-blocks/grc/blks2_tcp_sink.xml
@@ -7,6 +7,7 @@
<block>
<name>TCP Sink</name>
<key>blks2_tcp_sink</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.tcp_sink(
itemsize=$type.size*$vlen,
diff --git a/grc/blocks/blks2_tcp_source.xml b/gr-blocks/grc/blks2_tcp_source.xml
index 6bf742aa00..6a59522f3f 100644
--- a/grc/blocks/blks2_tcp_source.xml
+++ b/gr-blocks/grc/blks2_tcp_source.xml
@@ -7,6 +7,7 @@
<block>
<name>TCP Source</name>
<key>blks2_tcp_source</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.tcp_source(
itemsize=$type.size*$vlen,
diff --git a/grc/blocks/blks2_valve.xml b/gr-blocks/grc/blks2_valve.xml
index 47c553523f..d879ff655f 100644
--- a/grc/blocks/blks2_valve.xml
+++ b/gr-blocks/grc/blks2_valve.xml
@@ -8,6 +8,7 @@
<block>
<name>Valve</name>
<key>blks2_valve</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.valve(item_size=$type.size*$vlen, open=bool($open))</make>
<callback>set_open(bool($open))</callback>
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index f35815b4dd..bfab41aeb6 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -29,7 +29,7 @@
<cat>
<name></name> <!-- Blank for Root Name -->
<cat>
- <name>Audio</name>
+ <name>Audio</name>
<block>blocks_wavfile_source</block>
<block>blocks_wavfile_sink</block>
</cat>
@@ -230,4 +230,9 @@
<name>Variables</name>
<block>variable_tag_object</block>
</cat>
+ <cat>
+ <name>Misc</name>
+ <block>xmlrpc_server</block>
+ <block>xmlrpc_client</block>
+ </cat>
</cat>
diff --git a/gr-blocks/grc/blocks_repeat.xml b/gr-blocks/grc/blocks_repeat.xml
index c6c17c9900..793d0148b2 100644
--- a/gr-blocks/grc/blocks_repeat.xml
+++ b/gr-blocks/grc/blocks_repeat.xml
@@ -9,6 +9,7 @@
<key>blocks_repeat</key>
<import>from gnuradio import blocks</import>
<make>blocks.repeat($type.size*$vlen, $interp)</make>
+ <callback>set_interpolation($interp)</callback>
<param>
<name>Type</name>
<key>type</key>
diff --git a/grc/blocks/xmlrpc_client.xml b/gr-blocks/grc/xmlrpc_client.xml
index dc4d154d14..dc4d154d14 100644
--- a/grc/blocks/xmlrpc_client.xml
+++ b/gr-blocks/grc/xmlrpc_client.xml
diff --git a/grc/blocks/xmlrpc_server.xml b/gr-blocks/grc/xmlrpc_server.xml
index 602d444161..602d444161 100644
--- a/grc/blocks/xmlrpc_server.xml
+++ b/gr-blocks/grc/xmlrpc_server.xml
diff --git a/gr-blocks/include/gnuradio/blocks/repeat.h b/gr-blocks/include/gnuradio/blocks/repeat.h
index 622b066017..b34bda1ec5 100644
--- a/gr-blocks/include/gnuradio/blocks/repeat.h
+++ b/gr-blocks/include/gnuradio/blocks/repeat.h
@@ -32,6 +32,10 @@ namespace gr {
/*!
* \brief repeat each input \p repeat times
* \ingroup stream_operators_blk
+ *
+ * Message Ports:
+ * * interpolation (in):
+ * Takes a pmt_pair(pmt::mp("interpolation"), pmt_long interp), setting the interpolation to interp.
*/
class BLOCKS_API repeat : virtual public sync_interpolator
{
@@ -46,6 +50,20 @@ namespace gr {
* \param repeat number of times to repeat the input
*/
static sptr make(size_t itemsize, int repeat);
+
+ /*!
+ * \brief Return current interpolation
+ */
+ virtual int interpolation() const = 0;
+
+ /*!
+ * \brief sets the interpolation
+ *
+ * Call this method in a callback to adjust the interpolation at run time.
+ *
+ * \param interp interpolation to be set
+ */
+ virtual void set_interpolation(int interp) = 0;
};
} /* namespace blocks */
diff --git a/gr-blocks/include/gnuradio/blocks/vector_sink_X.h.t b/gr-blocks/include/gnuradio/blocks/vector_sink_X.h.t
index 527ebf7dff..a4ef38fd04 100644
--- a/gr-blocks/include/gnuradio/blocks/vector_sink_X.h.t
+++ b/gr-blocks/include/gnuradio/blocks/vector_sink_X.h.t
@@ -43,6 +43,7 @@ namespace gr {
static sptr make(int vlen = 1);
+ //! Clear the data and tags containers.
virtual void reset() = 0;
virtual std::vector<@TYPE@> data() const = 0;
virtual std::vector<tag_t> tags() const = 0;
diff --git a/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t b/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t
index d5298e8b47..b0ca6b869f 100644
--- a/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t
+++ b/gr-blocks/include/gnuradio/blocks/vector_source_X.h.t
@@ -76,6 +76,7 @@ namespace gr {
virtual void rewind() = 0;
virtual void set_data(const std::vector<@TYPE@> &data,
const std::vector<tag_t> &tags=std::vector<tag_t>()) = 0;
+ virtual void set_repeat(bool repeat) = 0;
};
} /* namespace blocks */
diff --git a/gr-blocks/lib/repeat_impl.cc b/gr-blocks/lib/repeat_impl.cc
index 9c2ccc63c8..fb62265134 100644
--- a/gr-blocks/lib/repeat_impl.cc
+++ b/gr-blocks/lib/repeat_impl.cc
@@ -43,6 +43,26 @@ namespace gr {
d_itemsize(itemsize),
d_interp(interp)
{
+ message_port_register_in(pmt::mp("interpolation"));
+ set_msg_handler(pmt::mp("interpolation"),
+ boost::bind(&repeat_impl::msg_set_interpolation, this, _1));
+ }
+
+ void
+ repeat_impl::msg_set_interpolation(pmt::pmt_t msg)
+ {
+ // Dynamization by Kevin McQuiggin:
+ d_interp = pmt::to_long(pmt::cdr(msg));
+ sync_interpolator::set_interpolation(d_interp);
+ }
+ void
+ repeat_impl::set_interpolation(int interp)
+ {
+ // This ensures that interpolation is only changed between calls to work
+ // (and not in the middle of an ongoing work)
+ _post( pmt::mp("interpolation"), /* port */
+ pmt::cons(pmt::mp("interpolation"), pmt::from_long(interp)) /* pair */
+ );
}
int
diff --git a/gr-blocks/lib/repeat_impl.h b/gr-blocks/lib/repeat_impl.h
index 1942729194..486a47a1ad 100644
--- a/gr-blocks/lib/repeat_impl.h
+++ b/gr-blocks/lib/repeat_impl.h
@@ -36,9 +36,15 @@ namespace gr {
public:
repeat_impl(size_t itemsize, int d_interp);
+ int interpolation() const { return d_interp; }
+ void set_interpolation(int interp);
+
+
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
+ private:
+ void msg_set_interpolation(pmt::pmt_t msg);
};
} /* namespace blocks */
diff --git a/gr-blocks/lib/tuntap_pdu_impl.cc b/gr-blocks/lib/tuntap_pdu_impl.cc
index 45995e4803..391b33937a 100644
--- a/gr-blocks/lib/tuntap_pdu_impl.cc
+++ b/gr-blocks/lib/tuntap_pdu_impl.cc
@@ -76,6 +76,14 @@ namespace gr {
if (d_fd <= 0)
throw std::runtime_error("gr::tuntap_pdu::make: tun_alloc failed (are you running as root?)");
+ int err = set_mtu(dev_cstr, MTU);
+ if(err < 0)
+ std::cerr << boost::format(
+ "gr::tuntap_pdu: failed to set MTU to %d.\n"
+ "You should use ifconfig to set the MTU. E.g.,\n"
+ " $ sudo ifconfig %s mtu %d\n"
+ ) % MTU % dev % MTU << std::endl;
+
std::cout << boost::format(
"Allocated virtual ethernet interface: %s\n"
"You must now use ifconfig to set its IP address. E.g.,\n"
@@ -140,6 +148,31 @@ namespace gr {
*/
return fd;
}
+
+ int
+ tuntap_pdu_impl::set_mtu(const char *dev, int MTU)
+ {
+ struct ifreq ifr;
+ int sfd, err;
+
+ /* MTU must be set by passing a socket fd to ioctl;
+ * create an arbitrary socket for this purpose
+ */
+ if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return sfd;
+
+ /* preparation of the struct ifr, of type "struct ifreq" */
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+ ifr.ifr_addr.sa_family = AF_INET; /* address family */
+ ifr.ifr_mtu = MTU;
+
+ /* try to set MTU */
+ if ((err = ioctl(sfd, SIOCSIFMTU, (void *) &ifr)) < 0)
+ return err;
+
+ return MTU;
+ }
#endif
} /* namespace blocks */
diff --git a/gr-blocks/lib/tuntap_pdu_impl.h b/gr-blocks/lib/tuntap_pdu_impl.h
index 360f954630..3a53e3acb5 100644
--- a/gr-blocks/lib/tuntap_pdu_impl.h
+++ b/gr-blocks/lib/tuntap_pdu_impl.h
@@ -40,6 +40,7 @@ namespace gr {
std::string d_dev;
bool d_istunflag;
int tun_alloc(char *dev, int flags);
+ int set_mtu(const char *dev, int MTU);
public:
tuntap_pdu_impl(std::string dev, int MTU, bool istunflag);
diff --git a/gr-blocks/lib/vector_sink_X_impl.h.t b/gr-blocks/lib/vector_sink_X_impl.h.t
index b5d3bd6432..86f0e8773c 100644
--- a/gr-blocks/lib/vector_sink_X_impl.h.t
+++ b/gr-blocks/lib/vector_sink_X_impl.h.t
@@ -41,7 +41,7 @@ namespace gr {
@NAME_IMPL@(int vlen);
~@NAME_IMPL@();
- void reset() { d_data.clear(); }
+ void reset() { d_data.clear(); d_tags.clear(); }
std::vector<@TYPE@> data() const;
std::vector<tag_t> tags() const;
diff --git a/gr-blocks/lib/vector_source_X_impl.h.t b/gr-blocks/lib/vector_source_X_impl.h.t
index 2641c6661b..bc9b329d8f 100644
--- a/gr-blocks/lib/vector_source_X_impl.h.t
+++ b/gr-blocks/lib/vector_source_X_impl.h.t
@@ -50,6 +50,7 @@ namespace gr {
void rewind() { d_offset=0; }
void set_data(const std::vector<@TYPE@> &data,
const std::vector<tag_t> &tags);
+ void set_repeat(bool repeat) { d_repeat=repeat; };
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-blocks/python/blocks/qa_block_behavior.py b/gr-blocks/python/blocks/qa_block_behavior.py
new file mode 100644
index 0000000000..a21e423b21
--- /dev/null
+++ b/gr-blocks/python/blocks/qa_block_behavior.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright 2016 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, blocks
+
+class test_block_behavior(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_000(self):
+ '''
+ Tests the max noutput sizes set by the scheduler. When creating
+ the block, there is no block_detail and so the max buffer size
+ is 0. When the top_block is run, it builds the detail and
+ buffers and sets the max value. test_0001 tests when the
+ max_noutput_items is set by hand.
+
+ '''
+
+ src = blocks.null_source(gr.sizeof_float)
+ op = blocks.head(gr.sizeof_float, 100)
+ snk = blocks.null_sink(gr.sizeof_float)
+
+ maxn_pre = op.max_noutput_items()
+
+ self.tb.connect(src, op, snk)
+ self.tb.run()
+
+ maxn_post = op.max_noutput_items()
+
+ self.assertEqual(maxn_pre, 0)
+ self.assertEqual(maxn_post, 16384)
+
+ def test_001(self):
+ '''
+ Tests the max noutput size when being explicitly set.
+ '''
+
+ src = blocks.null_source(gr.sizeof_float)
+ op = blocks.head(gr.sizeof_float, 100)
+ snk = blocks.null_sink(gr.sizeof_float)
+
+ op.set_max_noutput_items(1024)
+
+ maxn_pre = op.max_noutput_items()
+
+ self.tb.connect(src, op, snk)
+ self.tb.run()
+
+ maxn_post = op.max_noutput_items()
+
+ self.assertEqual(maxn_pre, 1024)
+ self.assertEqual(maxn_post, 1024)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_block_behavior, "test_block_behavior.xml")
diff --git a/gr-blocks/python/blocks/qa_vector_sink_source.py b/gr-blocks/python/blocks/qa_vector_sink_source.py
index 5dab7014cd..026713f5f4 100755
--- a/gr-blocks/python/blocks/qa_vector_sink_source.py
+++ b/gr-blocks/python/blocks/qa_vector_sink_source.py
@@ -46,6 +46,7 @@ class test_vector_sink_source(gr_unittest.TestCase):
self.tb = None
def test_001(self):
+ # Test that sink has data set in source for the simplest case
src_data = [float(x) for x in range(16)]
expected_result = tuple(src_data)
@@ -58,6 +59,7 @@ class test_vector_sink_source(gr_unittest.TestCase):
self.assertEqual(expected_result, result_data)
def test_002(self):
+ # Test vectors (the gnuradio vector I/O type)
src_data = [float(x) for x in range(16)]
expected_result = tuple(src_data)
@@ -70,11 +72,14 @@ class test_vector_sink_source(gr_unittest.TestCase):
self.assertEqual(expected_result, result_data)
def test_003(self):
+ # Test that we can only make vectors (the I/O type) if the input
+ # vector has sufficient size
src_data = [float(x) for x in range(16)]
expected_result = tuple(src_data)
self.assertRaises(RuntimeError, lambda : blocks.vector_source_f(src_data, False, 3))
def test_004(self):
+ # Test sending and receiving tagged streams
src_data = [float(x) for x in range(16)]
expected_result = tuple(src_data)
src_tags = tuple([make_tag('key', 'val', 0, 'src')])
@@ -92,6 +97,7 @@ class test_vector_sink_source(gr_unittest.TestCase):
self.assertTrue(compare_tags(expected_tags[0], result_tags[0]))
def test_005(self):
+ # Test that repeat works (with tagged streams)
length = 16
src_data = [float(x) for x in range(length)]
expected_result = tuple(src_data + src_data)
@@ -112,6 +118,36 @@ class test_vector_sink_source(gr_unittest.TestCase):
self.assertTrue(compare_tags(expected_tags[0], result_tags[0]))
self.assertTrue(compare_tags(expected_tags[1], result_tags[1]))
+ def test_006(self):
+ # Test set_data
+ src_data = [float(x) for x in range(16)]
+ expected_result = tuple(src_data)
+
+ src = blocks.vector_source_f((3,1,4))
+ dst = blocks.vector_sink_f()
+ src.set_data(src_data)
+
+ self.tb.connect(src, dst)
+ self.tb.run()
+ result_data = dst.data()
+ self.assertEqual(expected_result, result_data)
+
+ def test_007(self):
+ # Test set_repeat
+ src_data = [float(x) for x in range(16)]
+ expected_result = tuple(src_data)
+
+ src = blocks.vector_source_f(src_data, True)
+ dst = blocks.vector_sink_f()
+ src.set_repeat(False)
+
+ self.tb.connect(src, dst)
+ # will timeout if set_repeat does not work
+ self.tb.run()
+ result_data = dst.data()
+ self.assertEqual(expected_result, result_data)
+
+
if __name__ == '__main__':
gr_unittest.run(test_vector_sink_source, "test_vector_sink_source.xml")
diff --git a/grc/grc_gnuradio/CMakeLists.txt b/gr-blocks/python/grc_gnuradio/CMakeLists.txt
index e992a60a39..9ff1240997 100644
--- a/grc/grc_gnuradio/CMakeLists.txt
+++ b/gr-blocks/python/grc_gnuradio/CMakeLists.txt
@@ -18,18 +18,20 @@
# Boston, MA 02110-1301, USA.
########################################################################
+
+include(GrPython)
+
GR_PYTHON_INSTALL(
FILES __init__.py
DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio
- COMPONENT "grc"
+ COMPONENT "blocks_python"
)
GR_PYTHON_INSTALL(FILES
blks2/__init__.py
blks2/error_rate.py
- blks2/packet.py
blks2/selector.py
blks2/tcp.py
DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio/blks2
- COMPONENT "grc"
+ COMPONENT "blocks_python"
)
diff --git a/grc/grc_gnuradio/README b/gr-blocks/python/grc_gnuradio/README
index 897eed65ca..897eed65ca 100644
--- a/grc/grc_gnuradio/README
+++ b/gr-blocks/python/grc_gnuradio/README
diff --git a/grc/grc_gnuradio/__init__.py b/gr-blocks/python/grc_gnuradio/__init__.py
index 8b13789179..8b13789179 100644
--- a/grc/grc_gnuradio/__init__.py
+++ b/gr-blocks/python/grc_gnuradio/__init__.py
diff --git a/grc/grc_gnuradio/blks2/__init__.py b/gr-blocks/python/grc_gnuradio/blks2/__init__.py
index e6941ab91b..d3c8210834 100644
--- a/grc/grc_gnuradio/blks2/__init__.py
+++ b/gr-blocks/python/grc_gnuradio/blks2/__init__.py
@@ -19,8 +19,12 @@
#
from selector import selector, valve
-from packet import options, packet_encoder, packet_decoder, \
- packet_mod_b, packet_mod_s, packet_mod_i, packet_mod_f, packet_mod_c, \
- packet_demod_b, packet_demod_s, packet_demod_i, packet_demod_f, packet_demod_c
from error_rate import error_rate
from tcp import tcp_source, tcp_sink
+
+try:
+ from packet import options, packet_encoder, packet_decoder, \
+ packet_mod_b, packet_mod_s, packet_mod_i, packet_mod_f, packet_mod_c, \
+ packet_demod_b, packet_demod_s, packet_demod_i, packet_demod_f, packet_demod_c
+except ImportError:
+ pass # only available if gr-digital is install
diff --git a/grc/grc_gnuradio/blks2/error_rate.py b/gr-blocks/python/grc_gnuradio/blks2/error_rate.py
index 9bf387030a..9bf387030a 100644
--- a/grc/grc_gnuradio/blks2/error_rate.py
+++ b/gr-blocks/python/grc_gnuradio/blks2/error_rate.py
diff --git a/grc/grc_gnuradio/blks2/selector.py b/gr-blocks/python/grc_gnuradio/blks2/selector.py
index 24e3844658..24e3844658 100644
--- a/grc/grc_gnuradio/blks2/selector.py
+++ b/gr-blocks/python/grc_gnuradio/blks2/selector.py
diff --git a/grc/grc_gnuradio/blks2/tcp.py b/gr-blocks/python/grc_gnuradio/blks2/tcp.py
index aee90fad2c..aee90fad2c 100644
--- a/grc/grc_gnuradio/blks2/tcp.py
+++ b/gr-blocks/python/grc_gnuradio/blks2/tcp.py
diff --git a/gr-digital/CMakeLists.txt b/gr-digital/CMakeLists.txt
index 7a9f8f6c48..c6fa0798d1 100644
--- a/gr-digital/CMakeLists.txt
+++ b/gr-digital/CMakeLists.txt
@@ -97,6 +97,7 @@ add_subdirectory(doc)
if(ENABLE_PYTHON)
add_subdirectory(swig)
add_subdirectory(python/digital)
+ add_subdirectory(python/grc_gnuradio)
add_subdirectory(grc)
add_subdirectory(examples)
endif(ENABLE_PYTHON)
diff --git a/grc/blocks/blks2_packet_decoder.xml b/gr-digital/grc/blks2_packet_decoder.xml
index 07b0d1f2eb..c3672450ea 100644
--- a/grc/blocks/blks2_packet_decoder.xml
+++ b/gr-digital/grc/blks2_packet_decoder.xml
@@ -7,6 +7,7 @@
<block>
<name>Packet Decoder</name>
<key>blks2_packet_decoder</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.packet_demod_$(type.fcn)(grc_blks2.packet_decoder(
access_code=$access_code,
diff --git a/grc/blocks/blks2_packet_encoder.xml b/gr-digital/grc/blks2_packet_encoder.xml
index 88e1ba350c..92de9c9570 100644
--- a/grc/blocks/blks2_packet_encoder.xml
+++ b/gr-digital/grc/blks2_packet_encoder.xml
@@ -7,6 +7,7 @@
<block>
<name>Packet Encoder</name>
<key>blks2_packet_encoder</key>
+ <category>Deprecated</category>
<import>from grc_gnuradio import blks2 as grc_blks2</import>
<make>grc_blks2.packet_mod_$(type.fcn)(grc_blks2.packet_encoder(
samples_per_symbol=$samples_per_symbol,
diff --git a/gr-digital/grc/digital_constellation.xml b/gr-digital/grc/digital_constellation.xml
index 5254e4d799..ef5364d248 100644
--- a/gr-digital/grc/digital_constellation.xml
+++ b/gr-digital/grc/digital_constellation.xml
@@ -9,7 +9,13 @@
<key>variable_constellation</key>
<category>Modulators</category>
<import>from gnuradio import digital</import>
- <var_make>self.$(id) = $(id) = digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims).base()
+ <var_make>
+#if str($type) == "calcdist"
+self.$(id) = $(id) = digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims).base()
+#else
+self.$(id) = $(id) = digital.constellation_$(type)().base()
+#end if
+
#if str($soft_dec_lut).lower() == '"auto"' or str($soft_dec_lut).lower() == "'auto'"
self.$(id).gen_soft_dec_lut($precision)
#else if str($soft_dec_lut) != 'None'
@@ -17,16 +23,53 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision)
#end if
</var_make>
- <var_value>digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims)</var_value>
+<var_value>
+#if str($type) == "calcdist"
+digital.constellation_calcdist($const_points, $sym_map, $rot_sym, $dims)
+#else
+digital.constellation_$(type)()
+#end if
+</var_value>
<make></make>
<!--<callback></callback>-->
<param>
+ <name>Constellation Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Variable Constellation</name>
+ <key>calcdist</key>
+ </option>
+ <option>
+ <name>BPSK</name>
+ <key>bpsk</key>
+ </option>
+ <option>
+ <name>QPSK</name>
+ <key>qpsk</key>
+ </option>
+ <option>
+ <name>DQPSK</name>
+ <key>dqpsk</key>
+ </option>
+ <option>
+ <name>8PSK</name>
+ <key>8psk</key>
+ </option>
+ <option>
+ <name>16QAM</name>
+ <key>16qam</key>
+ </option>
+
+ </param>
+ <param>
<name>Symbol Map</name>
<key>sym_map</key>
<value>[0, 1, 3, 2]</value>
<type>int_vector</type>
+ <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide>
</param>
<param>
@@ -34,6 +77,7 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision)
<key>const_points</key>
<value>[-1-1j, -1+1j, 1+1j, 1-1j]</value>
<type>complex_vector</type>
+ <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide>
</param>
<param>
@@ -41,6 +85,7 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision)
<key>rot_sym</key>
<value>4</value>
<type>int</type>
+ <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide>
</param>
<param>
@@ -48,8 +93,8 @@ self.$(id).set_soft_dec_lut($soft_dec_lut, $precision)
<key>dims</key>
<value>1</value>
<type>int</type>
+ <hide> #if str($type) == "calcdist" then 'none' else 'all' #</hide>
</param>
-
<param>
<name>Soft Decisions Precision</name>
<key>precision</key>
diff --git a/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py b/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py
new file mode 100755
index 0000000000..5429ce1e07
--- /dev/null
+++ b/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+#
+# Copyright 2006,2007,2010,2011,2013,2016 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, digital, blocks
+import pmt
+
+default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC'
+
+def string_to_1_0_list(s):
+ r = []
+ for ch in s:
+ x = ord(ch)
+ for i in range(8):
+ t = (x >> i) & 0x1
+ r.append(t)
+ return r
+
+def to_1_0_string(L):
+ return ''.join(map(lambda x: chr(x + ord('0')), L))
+
+class test_correlate_access_code_XX_ts(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_001(self):
+ payload = "test packet" # payload length is 11 bytes
+ header = "\x00\xd0\x00\xd0" # header contains packet length, twice (bit-swapped)
+ packet = header + payload
+ pad = (0,) * 64
+ src_data = (0, 0, 1, 1, 1, 1, 0, 1, 1) + tuple(string_to_1_0_list(packet)) + pad
+ expected = tuple(map(long, src_data[9+32:-len(pad)]))
+ src = blocks.vector_source_b(src_data)
+ op = digital.correlate_access_code_bb_ts("1011", 0, "sync")
+ dst = blocks.vector_sink_b()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ result_tags = dst.tags()
+ self.assertEqual(len(result_data), len(payload)*8)
+ self.assertEqual(result_tags[0].offset, 0)
+ self.assertEqual(pmt.to_long(result_tags[0].value), len(payload)*8)
+ self.assertEqual(result_data, expected)
+
+ def test_002(self):
+ payload = "test packet" # payload length is 11 bytes
+ header = "\x00\xd0\x00\xd0" # header contains packet length, twice (bit-swapped)
+ packet = header + payload
+ pad = (0,) * 64
+ src_data = (0, 0, 1, 1, 1, 1, 0, 1, 1) + tuple(string_to_1_0_list(packet)) + pad
+ src_floats = tuple(2*b-1 for b in src_data) # convert to binary antipodal symbols (-1,1)
+ expected = src_floats[9+32:-len(pad)]
+ src = blocks.vector_source_f(src_floats)
+ op = digital.correlate_access_code_ff_ts("1011", 0, "sync")
+ dst = blocks.vector_sink_f()
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = dst.data()
+ result_tags = dst.tags()
+ self.assertEqual(len(result_data), len(payload)*8)
+ self.assertEqual(result_tags[0].offset, 0)
+ self.assertEqual(pmt.to_long(result_tags[0].value), len(payload)*8)
+ self.assertFloatTuplesAlmostEqual(result_data, expected, 5)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(test_correlate_access_code_XX_ts, "test_correlate_access_code_XX_ts.xml")
+
diff --git a/grc/base/CMakeLists.txt b/gr-digital/python/grc_gnuradio/CMakeLists.txt
index bdc8a5006f..f021299f1a 100644
--- a/grc/base/CMakeLists.txt
+++ b/gr-digital/python/grc_gnuradio/CMakeLists.txt
@@ -18,26 +18,13 @@
# Boston, MA 02110-1301, USA.
########################################################################
-GR_PYTHON_INSTALL(FILES
- odict.py
- ParseXML.py
- Block.py
- Connection.py
- Constants.py
- Element.py
- FlowGraph.py
- Param.py
- Platform.py
- Port.py
- __init__.py
- DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/base
- COMPONENT "grc"
-)
-install(FILES
- block_tree.dtd
- domain.dtd
- flow_graph.dtd
- DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/base
- COMPONENT "grc"
+include(GrPython)
+
+# __init__ files come from gr-blocks
+
+GR_PYTHON_INSTALL(FILES
+ blks2/packet.py
+ DESTINATION ${GR_PYTHON_DIR}/grc_gnuradio/blks2
+ COMPONENT "digital_python"
)
diff --git a/grc/grc_gnuradio/blks2/packet.py b/gr-digital/python/grc_gnuradio/blks2/packet.py
index ef79afde64..ef79afde64 100644
--- a/grc/grc_gnuradio/blks2/packet.py
+++ b/gr-digital/python/grc_gnuradio/blks2/packet.py
diff --git a/gr-dtv/CMakeLists.txt b/gr-dtv/CMakeLists.txt
index fc7ab56bef..5a23482b26 100644
--- a/gr-dtv/CMakeLists.txt
+++ b/gr-dtv/CMakeLists.txt
@@ -41,6 +41,8 @@ GR_SET_GLOBAL(GR_DTV_INCLUDE_DIRS
${CMAKE_CURRENT_BINARY_DIR}/lib
)
+SET(GR_PKG_DTV_EXAMPLES_DIR ${GR_PKG_DATA_DIR}/examples/dtv)
+
########################################################################
# Begin conditional configuration
########################################################################
diff --git a/gr-dtv/examples/CMakeLists.txt b/gr-dtv/examples/CMakeLists.txt
index 82b663d924..8f209bce4f 100644
--- a/gr-dtv/examples/CMakeLists.txt
+++ b/gr-dtv/examples/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2014 Free Software Foundation, Inc.
+# Copyright 2014-2015 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -21,6 +21,31 @@ include(GrPython)
GR_PYTHON_INSTALL(
PROGRAMS
+ atsc_ctrlport_monitor.py
+ DESTINATION ${GR_PKG_DTV_EXAMPLES_DIR}
+ COMPONENT "dtv_python"
+)
+
+install(
+ FILES
+ README.dvbs
+ README.dvbs2
+ README.dvbt
+ README.dvbt2
+ README.catv
+ dvbs2_tx.grc
+ dvbs_tx.grc
+ dvbt_rx_8k.grc
+ dvbt_tx_2k.grc
+ dvbt_tx_8k.grc
+ file_atsc_rx.grc
+ file_atsc_tx.grc
+ uhd_atsc_capture.grc
+ uhd_rx_atsc.grc
+ vv003-cr23.grc
+ vv009-4kfft.grc
+ vv018-miso.grc
+ catv_tx_64qam.grc
DESTINATION ${GR_PKG_DTV_EXAMPLES_DIR}
COMPONENT "dtv_python"
)
diff --git a/gr-dtv/examples/README.catv b/gr-dtv/examples/README.catv
new file mode 100644
index 0000000000..84c4cd0b26
--- /dev/null
+++ b/gr-dtv/examples/README.catv
@@ -0,0 +1,31 @@
+A test Transport Stream (26.970352 Mbps) for the example flow graph
+is available here:
+
+http://www.w6rz.net/advqam64.ts
+
+It is 357,356,980 bytes.
+
+The three parameters Control_Word, I_taps and J_increment can be
+used to control the interleaver from the following table.
+
+Control_Word I_taps J_increment Burst protection Latency
+ 0 128 1 95 us 4 ms
+ 1 128 1 95 us 4 ms
+ 2 128 2 190 us 8 ms
+ 3 64 2 47 us 2 ms
+ 4 128 3 285 us 12 ms
+ 5 32 4 24 us 0.98 ms
+ 6 128 4 379 us 16 ms
+ 7 16 8 12 us 0.48 ms
+ 8 128 5 474 us 20 ms
+ 9 8 16 5.9 us 0.22 ms
+ 10 128 6 569 us 24 ms
+ 11 Reserved
+ 12 128 7 664 us 28 ms
+ 13 Reserved
+ 14 128 8 759 us 32 ms
+ 15 Reserved
+
+The default is Control_Word = 6, I_taps = 128 and J_increment = 4
+which seems to be the most commonly used on CATV systems.
+
diff --git a/gr-dtv/examples/README.dvbs b/gr-dtv/examples/README.dvbs
new file mode 100644
index 0000000000..d9097c4876
--- /dev/null
+++ b/gr-dtv/examples/README.dvbs
@@ -0,0 +1,26 @@
+Puncturing values for DVB-S code rates:
+
+1/2 code rate = Puncture Size = 2, Puncture Pattern = 0b11
+2/3 code rate = Puncture Size = 4, Puncture Pattern = 0b1101
+3/4 code rate = Puncture Size = 6, Puncture Pattern = 0b110110
+5/6 code rate = Puncture Size = 10, Puncture Pattern = 0b1101100110
+7/8 code rate = Puncture Size = 14, Puncture Pattern = 0b11010101100110
+
+A test Transport Stream for the example flow graph
+(8 Msyms/s and 7/8 code rate) is available here:
+
+http://www.w6rz.net/advdvbs78.ts
+
+It is 170,950,844 bytes.
+
+This stream can also be used at:
+
+14 Msyms/s 1/2 code rate
+10.5 MSyms/s 2/3 code rate
+9.333333 MSyms/s 3/4 code rate
+8.4 Msyms/s 5/6 code rate
+
+The equation for calculating the correct Transport Stream bit-rate is:
+
+TS bit-rate = symbol rate * 2 * code rate * (188 / 204)
+
diff --git a/gr-dtv/examples/atsc_ctrlport_monitor.py b/gr-dtv/examples/atsc_ctrlport_monitor.py
new file mode 100755
index 0000000000..7c43aebb77
--- /dev/null
+++ b/gr-dtv/examples/atsc_ctrlport_monitor.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 Free Software Foundation
+#
+# This program 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 program 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; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import sys
+import matplotlib
+matplotlib.use("QT4Agg")
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient
+import scipy
+from scipy import fftpack
+
+"""
+If a host is running the ATSC receiver chain with ControlPort
+turned on, this script will connect to the host using the hostname and
+port pair of the ControlPort instance and display metrics of the
+receiver. The ATSC publishes information about the succes of the
+Reed-Solomon decoder and Viterbi metrics for use here in displaying
+the link quality. This also gets the equalizer taps of the receiver
+and displays the frequency response.
+"""
+
+class atsc_ctrlport_monitor:
+ def __init__(self, host, port):
+ argv = [None, host, port]
+ radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift')
+ self.radio = radiosys.client
+ print self.radio
+
+
+ vt_init_key = 'dtv_atsc_viterbi_decoder0::decoder_metrics'
+ data = self.radio.getKnobs([vt_init_key])[vt_init_key]
+ init_metric = scipy.mean(data.value)
+ self._viterbi_metric = 100*[init_metric,]
+
+ table_col_labels = ('Num Packets', 'Error Rate', 'Packet Error Rate',
+ 'Viterbi Metric', 'SNR')
+
+ self._fig = plt.figure(1, figsize=(12,12), facecolor='w')
+ self._sp0 = self._fig.add_subplot(4,1,1)
+ self._sp1 = self._fig.add_subplot(4,1,2)
+ self._sp2 = self._fig.add_subplot(4,1,3)
+ self._plot_taps = self._sp0.plot([], [], 'k', linewidth=2)
+ self._plot_psd = self._sp1.plot([], [], 'k', linewidth=2)
+ self._plot_data = self._sp2.plot([], [], 'ok', linewidth=2, markersize=4, alpha=0.05)
+
+ self._ax2 = self._fig.add_subplot(4,1,4)
+ self._table = self._ax2.table(cellText=[len(table_col_labels)*['0']],
+ colLabels=table_col_labels,
+ loc='center')
+ self._ax2.axis('off')
+ cells = self._table.properties()['child_artists']
+ for c in cells:
+ c.set_lw(0.1) # set's line width
+ c.set_ls('solid')
+ c.set_height(0.2)
+
+ ani = animation.FuncAnimation(self._fig, self.update_data, frames=200,
+ fargs=(self._plot_taps[0], self._plot_psd[0],
+ self._plot_data[0], self._table),
+ init_func=self.init_function,
+ blit=True)
+ plt.show()
+
+ def update_data(self, x, taps, psd, syms, table):
+ try:
+ eqdata_key = 'dtv_atsc_equalizer0::taps'
+ symdata_key = 'dtv_atsc_equalizer0::data'
+ rs_nump_key = 'dtv_atsc_rs_decoder0::num_packets'
+ rs_numbp_key = 'dtv_atsc_rs_decoder0::num_bad_packets'
+ rs_numerrs_key = 'dtv_atsc_rs_decoder0::num_errors_corrected'
+ vt_metrics_key = 'dtv_atsc_viterbi_decoder0::decoder_metrics'
+ snr_key = 'probe2_f0::SNR'
+
+ data = self.radio.getKnobs([])
+ eqdata = data[eqdata_key]
+ symdata = data[symdata_key]
+ rs_num_packets = data[rs_nump_key]
+ rs_num_bad_packets = data[rs_numbp_key]
+ rs_num_errors_corrected = data[rs_numerrs_key]
+ vt_decoder_metrics = data[vt_metrics_key]
+ snr_est = data[snr_key]
+
+ vt_decoder_metrics = scipy.mean(vt_decoder_metrics.value)
+ self._viterbi_metric.pop()
+ self._viterbi_metric.insert(0, vt_decoder_metrics)
+
+ except:
+ sys.stderr.write("Lost connection, exiting")
+ sys.exit(1)
+
+ ntaps = len(eqdata.value)
+ taps.set_ydata(eqdata.value)
+ taps.set_xdata(xrange(ntaps))
+ self._sp0.set_xlim(0, ntaps)
+ self._sp0.set_ylim(min(eqdata.value), max(eqdata.value))
+
+ fs = 6.25e6
+ freq = scipy.linspace(-fs/2, fs/2, 10000)
+ H = fftpack.fftshift(fftpack.fft(eqdata.value, 10000))
+ HdB = 20.0*scipy.log10(abs(H))
+ psd.set_ydata(HdB)
+ psd.set_xdata(freq)
+ self._sp1.set_xlim(0, fs/2)
+ self._sp1.set_ylim([min(HdB), max(HdB)])
+ self._sp1.set_yticks([min(HdB), max(HdB)])
+ self._sp1.set_yticklabels(["min", "max"])
+
+ nsyms = len(symdata.value)
+ syms.set_ydata(symdata.value)
+ syms.set_xdata(nsyms*[0,])
+ self._sp2.set_xlim([-1, 1])
+ self._sp2.set_ylim([-10, 10])
+
+ per = float(rs_num_bad_packets.value) / float(rs_num_packets.value)
+ ber = float(rs_num_errors_corrected.value) / float(187*rs_num_packets.value)
+
+ table._cells[(1,0)]._text.set_text("{0}".format(rs_num_packets.value))
+ table._cells[(1,1)]._text.set_text("{0:.2g}".format(ber))
+ table._cells[(1,2)]._text.set_text("{0:.2g}".format(per))
+ table._cells[(1,3)]._text.set_text("{0:.1f}".format(scipy.mean(self._viterbi_metric)))
+ table._cells[(1,4)]._text.set_text("{0:.4f}".format(snr_est.value[0]))
+
+ return (taps, psd, syms, table)
+
+ def init_function(self):
+ return self._plot_taps + self._plot_psd + self._plot_data
+
+if __name__ == "__main__":
+ host = sys.argv[1]
+ port = sys.argv[2]
+ m = atsc_ctrlport_monitor(host, port)
diff --git a/gr-dtv/examples/catv_tx_64qam.grc b/gr-dtv/examples/catv_tx_64qam.grc
new file mode 100644
index 0000000000..964ef8470f
--- /dev/null
+++ b/gr-dtv/examples/catv_tx_64qam.grc
@@ -0,0 +1,2079 @@
+<?xml version='1.0' encoding='utf-8'?>
+<?grc format='1' created='3.7.10'?>
+<flow_graph>
+ <timestamp>Thu Feb 20 21:02:41 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>hier_block_src_path</key>
+ <value>.:</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>catv_tx_64qam</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>qt_qss_theme</key>
+ <value></value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>run_command</key>
+ <value>{python} -u {filename}</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></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>(8, 299)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>Control_Word</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>6</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>(8, 371)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>I_taps</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>128</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>(8, 443)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>J_increment</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>4</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>(8, 155)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>center_freq</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>429000000</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>(8, 227)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>rrc_taps</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100</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>(8, 83)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>5056941 * 2</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>int_converter</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>-8</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(312, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>vga1_gain</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>VGA1 Gain</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>-4</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>-35</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>31</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ </block>
+ <block>
+ <key>variable_slider</key>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>converver</key>
+ <value>int_converter</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(448, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>vga2_gain</value>
+ </param>
+ <param>
+ <key>label</key>
+ <value>VGA2 Gain</value>
+ </param>
+ <param>
+ <key>max</key>
+ <value>25</value>
+ </param>
+ <param>
+ <key>min</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>num_steps</key>
+ <value>25</value>
+ </param>
+ <param>
+ <key>style</key>
+ <value>wx.SL_HORIZONTAL</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_source</key>
+ <param>
+ <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>file</key>
+ <value>/run/shm/advqam64.ts</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(128, 163)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_file_source_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</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>
+ </block>
+ <block>
+ <key>blocks_packed_to_unpacked_xx</key>
+ <param>
+ <key>bits_per_chunk</key>
+ <value>7</value>
+ </param>
+ <param>
+ <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>endianness</key>
+ <value>gr.GR_MSB_FIRST</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(624, 163)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_packed_to_unpacked_xx_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_stream_to_vector</key>
+ <param>
+ <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>_coordinate</key>
+ <value>(536, 251)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>180</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_stream_to_vector_0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>num_items</key>
+ <value>I_taps</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_catv_frame_sync_enc_bb</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ctrlword</key>
+ <value>Control_Word</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(584, 347)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_catv_frame_sync_enc_bb_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_catv_randomizer_bb</key>
+ <param>
+ <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>_coordinate</key>
+ <value>(424, 353)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_catv_randomizer_bb_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_catv_reed_solomon_enc_bb</key>
+ <param>
+ <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>_coordinate</key>
+ <value>(848, 177)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_catv_reed_solomon_enc_bb_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_catv_transport_framing_enc_bb</key>
+ <param>
+ <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>_coordinate</key>
+ <value>(360, 177)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_catv_transport_framing_enc_bb_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_catv_trellis_enc_bb</key>
+ <param>
+ <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>_coordinate</key>
+ <value>(800, 353)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_catv_trellis_enc_bb_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbs2_modulator_bc</key>
+ <param>
+ <key>interpolation</key>
+ <value>INTERPOLATION_ON</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>rate</key>
+ <value>C_OTHER</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>MOD_64QAM</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(400, 499)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbs2_modulator_bc_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_convolutional_interleaver</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>M</key>
+ <value>J_increment</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(168, 339)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_convolutional_interleaver_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>I</key>
+ <value>I_taps</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_filter_xxx</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(712, 507)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>fft_filter_xxx_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(0.14, samp_rate, samp_rate/2, 0.18, rrc_taps)</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccf</value>
+ </param>
+ </block>
+ <block>
+ <key>osmosdr_sink</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain0</key>
+ <value>vga1_gain</value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>6000000</value>
+ </param>
+ <param>
+ <key>corr0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq0</key>
+ <value>center_freq</value>
+ </param>
+ <param>
+ <key>if_gain0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>vga2_gain</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain10</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq10</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain10</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain11</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq11</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain11</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain12</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq12</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain12</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain13</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq13</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain13</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain14</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq14</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain14</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain15</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq15</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain15</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain16</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq16</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain16</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain17</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq17</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain17</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain18</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq18</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain18</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain19</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq19</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain19</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain1</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq1</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain1</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain20</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq20</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain20</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain21</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq21</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain21</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain22</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq22</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain22</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain23</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq23</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain23</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain24</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq24</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain24</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain25</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq25</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain25</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain26</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq26</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain26</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain27</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq27</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain27</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain28</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq28</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain28</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain29</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq29</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain29</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain2</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq2</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain2</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain2</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain30</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq30</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain30</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain31</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq31</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain31</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain3</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq3</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain3</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain4</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq4</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain4</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain5</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq5</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain5</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain6</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq6</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain6</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain7</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq7</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain7</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain8</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq8</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain8</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain9</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq9</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain9</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain9</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>args</key>
+ <value>bladerf=0,buffers=128,buflen=32768</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1056, 467)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>osmosdr_sink_0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>sample_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>avg_alpha</key>
+ <value>0.1333</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>center_freq</value>
+ </param>
+ <param>
+ <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>1</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1056, 203)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0_0</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>-10</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value>640,480</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>blocks_file_source_0</source_block_id>
+ <sink_block_id>dtv_catv_transport_framing_enc_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_packed_to_unpacked_xx_0</source_block_id>
+ <sink_block_id>dtv_catv_reed_solomon_enc_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_stream_to_vector_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>
+ <connection>
+ <source_block_id>dtv_catv_frame_sync_enc_bb_0</source_block_id>
+ <sink_block_id>dtv_catv_trellis_enc_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_catv_randomizer_bb_0</source_block_id>
+ <sink_block_id>dtv_catv_frame_sync_enc_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_catv_reed_solomon_enc_bb_0</source_block_id>
+ <sink_block_id>blocks_stream_to_vector_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_catv_transport_framing_enc_bb_0</source_block_id>
+ <sink_block_id>blocks_packed_to_unpacked_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_catv_trellis_enc_bb_0</source_block_id>
+ <sink_block_id>dtv_dvbs2_modulator_bc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbs2_modulator_bc_0</source_block_id>
+ <sink_block_id>fft_filter_xxx_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_catv_randomizer_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>osmosdr_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/gr-dtv/examples/dvbs2_tx.grc b/gr-dtv/examples/dvbs2_tx.grc
index 47daa4cb9d..c6de308ae3 100644
--- a/gr-dtv/examples/dvbs2_tx.grc
+++ b/gr-dtv/examples/dvbs2_tx.grc
@@ -1,23 +1,23 @@
-<?xml version='1.0' encoding='ASCII'?>
-<?grc format='1' created='3.7.7'?>
+<?xml version='1.0' encoding='utf-8'?>
+<?grc format='1' created='3.7.10'?>
<flow_graph>
<timestamp>Wed Sep 3 03:03:39 2014</timestamp>
<block>
<key>options</key>
<param>
- <key>id</key>
- <value>dvbs2_tx</value>
+ <key>author</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>window_size</key>
+ <value>1280, 1024</value>
</param>
<param>
- <key>title</key>
- <value></value>
+ <key>category</key>
+ <value>Custom</value>
</param>
<param>
- <key>author</key>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -25,16 +25,44 @@
<value></value>
</param>
<param>
- <key>window_size</key>
- <value>1280, 1024</value>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
<key>generate_options</key>
<value>wx_gui</value>
</param>
<param>
- <key>category</key>
- <value>Custom</value>
+ <key>hier_block_src_path</key>
+ <value>.:</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dvbs2_tx</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>qt_qss_theme</key>
+ <value></value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>run_command</key>
+ <value>{python} -u {filename}</value>
</param>
<param>
<key>run_options</key>
@@ -45,45 +73,79 @@
<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>
+ <key>title</key>
<value></value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(8, 11)</value>
+ <value>(8, 203)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>frequency</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1280e6</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>(8, 267)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>rolloff</value>
+ </param>
+ <param>
<key>value</key>
- <value>symbol_rate * 2</value>
+ <value>0.2</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
<value>(8, 75)</value>
</param>
@@ -91,107 +153,186 @@
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>symbol_rate * 2</value>
+ </param>
</block>
<block>
<key>variable</key>
<param>
- <key>id</key>
- <value>symbol_rate</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
+ <key>_coordinate</key>
+ <value>(8, 139)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>symbol_rate</value>
+ </param>
+ <param>
<key>value</key>
<value>5000000</value>
</param>
+ </block>
+ <block>
+ <key>variable</key>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(8, 139)</value>
+ <value>(8, 331)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
<key>id</key>
- <value>rolloff</value>
+ <value>taps</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>value</key>
+ <value>100</value>
</param>
+ </block>
+ <block>
+ <key>blocks_file_sink</key>
<param>
- <key>value</key>
- <value>0.2</value>
+ <key>append</key>
+ <value>False</value>
</param>
<param>
<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>False</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>adv.cfile</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(8, 203)</value>
+ <value>(784, 547)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>variable</key>
<param>
<key>id</key>
- <value>taps</value>
+ <value>blocks_file_sink_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>type</key>
+ <value>complex</value>
</param>
<param>
- <key>value</key>
- <value>50</value>
+ <key>unbuffered</key>
+ <value>False</value>
</param>
<param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_source</key>
+ <param>
<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>file</key>
+ <value>/run/shm/adv16apsk910.ts</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(8, 267)</value>
+ <value>(176, 43)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>dtv_dvb_bch_bb</key>
<param>
<key>id</key>
- <value>dtv_dvb_bch_bb_0</value>
+ <value>blocks_file_source_0</value>
</param>
<param>
- <key>_enabled</key>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ <param>
+ <key>repeat</key>
<value>True</value>
</param>
<param>
- <key>standard</key>
- <value>STANDARD_DVBS2</value>
+ <key>vlen</key>
+ <value>1</value>
</param>
+ </block>
+ <block>
+ <key>dtv_dvb_bbheader_bb</key>
<param>
- <key>framesize</key>
+ <key>mode</key>
<value>FECFRAME_NORMAL</value>
</param>
<param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
<key>rate1</key>
<value>C1_2</value>
</param>
@@ -208,7 +349,7 @@
<value>C1_4</value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -216,39 +357,59 @@
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>fecblocks</key>
+ <value>168</value>
+ </param>
+ <param>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
</param>
<param>
<key>_coordinate</key>
- <value>(824, 35)</value>
+ <value>(400, 27)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>dtv_dvb_bbscrambler_bb</key>
<param>
<key>id</key>
- <value>dtv_dvb_bbscrambler_bb_0</value>
+ <value>dtv_dvb_bbheader_bb_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>inband</key>
+ <value>INBAND_OFF</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>rolloff</key>
+ <value>RO_0_20</value>
</param>
<param>
<key>standard</key>
<value>STANDARD_DVBS2</value>
</param>
<param>
- <key>framesize</key>
- <value>FECFRAME_NORMAL</value>
+ <key>tsrate</key>
+ <value>4000000</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvb_bbscrambler_bb</key>
+ <param>
+ <key>alias</key>
+ <value></value>
</param>
<param>
<key>rate1</key>
@@ -267,7 +428,7 @@
<value>C1_4</value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -275,12 +436,12 @@
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
</param>
<param>
<key>_coordinate</key>
@@ -290,24 +451,28 @@
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>dtv_dvb_ldpc_bb</key>
<param>
<key>id</key>
- <value>dtv_dvb_ldpc_bb_0</value>
+ <value>dtv_dvb_bbscrambler_bb_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
<key>standard</key>
<value>STANDARD_DVBS2</value>
</param>
+ </block>
+ <block>
+ <key>dtv_dvb_bch_bb</key>
<param>
- <key>framesize</key>
- <value>FECFRAME_NORMAL</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
<key>rate1</key>
@@ -326,11 +491,7 @@
<value>C1_4</value>
</param>
<param>
- <key>constellation</key>
- <value>MOD_OTHER</value>
- </param>
- <param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
@@ -338,239 +499,310 @@
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1048, 27)</value>
+ <value>(824, 35)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvb_bch_bb_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>standard</key>
+ <value>STANDARD_DVBS2</value>
+ </param>
</block>
<block>
- <key>dtv_dvbs2_interleaver_bb</key>
+ <key>dtv_dvb_ldpc_bb</key>
<param>
- <key>id</key>
- <value>dtv_dvbs2_interleaver_bb_0</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>rate1</key>
+ <value>C1_2</value>
</param>
<param>
- <key>framesize</key>
- <value>FECFRAME_NORMAL</value>
+ <key>rate2</key>
+ <value>C1_3</value>
</param>
<param>
- <key>constellation</key>
- <value>MOD_16APSK</value>
+ <key>rate3</key>
+ <value>C9_10</value>
</param>
<param>
- <key>rate</key>
- <value>C_OTHER</value>
+ <key>rate4</key>
+ <value>C1_4</value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>constellation</key>
+ <value>MOD_OTHER</value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
</param>
<param>
<key>_coordinate</key>
- <value>(192, 235)</value>
+ <value>(1048, 27)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>wxgui_fftsink2</key>
<param>
<key>id</key>
- <value>wxgui_fftsink2_0</value>
+ <value>dtv_dvb_ldpc_bb_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>title</key>
- <value>FFT Plot</value>
+ <key>standard</key>
+ <value>STANDARD_DVBS2</value>
</param>
+ </block>
+ <block>
+ <key>dtv_dvbs2_interleaver_bb</key>
<param>
- <key>samp_rate</key>
- <value>samp_rate</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>baseband_freq</key>
- <value>1280000000</value>
+ <key>rate</key>
+ <value>C_OTHER</value>
</param>
<param>
- <key>y_per_div</key>
- <value>10</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>y_divs</key>
- <value>10</value>
+ <key>constellation</key>
+ <value>MOD_16APSK</value>
</param>
<param>
- <key>ref_level</key>
- <value>0</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
- <key>ref_scale</key>
- <value>2.0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>fft_size</key>
- <value>1024</value>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
</param>
<param>
- <key>fft_rate</key>
- <value>15</value>
+ <key>_coordinate</key>
+ <value>(192, 235)</value>
</param>
<param>
- <key>peak_hold</key>
- <value>False</value>
+ <key>_rotation</key>
+ <value>0</value>
</param>
<param>
- <key>average</key>
- <value>True</value>
+ <key>id</key>
+ <value>dtv_dvbs2_interleaver_bb_0</value>
</param>
<param>
- <key>avg_alpha</key>
- <value>0.13333</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>win</key>
- <value>None</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>dtv_dvbs2_modulator_bc</key>
<param>
- <key>win_size</key>
- <value></value>
+ <key>interpolation</key>
+ <value>INTERPOLATION_OFF</value>
</param>
<param>
- <key>grid_pos</key>
+ <key>alias</key>
<value></value>
</param>
<param>
- <key>notebook</key>
- <value></value>
+ <key>rate</key>
+ <value>C9_10</value>
</param>
<param>
- <key>freqvar</key>
- <value>None</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>constellation</key>
+ <value>MOD_16APSK</value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(1000, 395)</value>
+ <value>(472, 227)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>dtv_dvbs2_modulator_bc</key>
<param>
<key>id</key>
<value>dtv_dvbs2_modulator_bc_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>maxoutbuf</key>
+ <value>0</value>
</param>
<param>
- <key>framesize</key>
- <value>FECFRAME_NORMAL</value>
+ <key>minoutbuf</key>
+ <value>0</value>
</param>
+ </block>
+ <block>
+ <key>dtv_dvbs2_physical_cc</key>
<param>
- <key>constellation</key>
- <value>MOD_16APSK</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
<key>rate</key>
<value>C9_10</value>
</param>
<param>
- <key>alias</key>
+ <key>comment</key>
<value></value>
</param>
<param>
+ <key>constellation</key>
+ <value>MOD_16APSK</value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
</param>
<param>
<key>_coordinate</key>
- <value>(472, 235)</value>
+ <value>(192, 443)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>goldcode</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbs2_physical_cc_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>pilots</key>
+ <value>PILOTS_ON</value>
+ </param>
</block>
<block>
<key>fft_filter_xxx</key>
<param>
- <key>id</key>
- <value>fft_filter_xxx_0</value>
+ <key>alias</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>comment</key>
+ <value></value>
</param>
<param>
- <key>type</key>
- <value>ccc</value>
+ <key>affinity</key>
+ <value></value>
</param>
<param>
<key>decim</key>
<value>1</value>
</param>
<param>
- <key>taps</key>
- <value>firdes.root_raised_cosine(1, samp_rate, samp_rate/2, rolloff, taps)</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>samp_delay</key>
+ <key>_coordinate</key>
+ <value>(472, 459)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>fft_filter_xxx_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
<value>0</value>
</param>
<param>
@@ -578,1014 +810,1458 @@
<value>1</value>
</param>
<param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(1.0, samp_rate, samp_rate/2, rolloff, taps)</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccc</value>
+ </param>
+ </block>
+ <block>
+ <key>osmosdr_sink</key>
+ <param>
<key>alias</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>ant0</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
+ <key>bb_gain0</key>
+ <value>-10</value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>6000000</value>
+ </param>
+ <param>
+ <key>corr0</key>
<value>0</value>
</param>
<param>
- <key>maxoutbuf</key>
+ <key>freq0</key>
+ <value>frequency</value>
+ </param>
+ <param>
+ <key>if_gain0</key>
<value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(472, 459)</value>
+ <key>gain0</key>
+ <value>15</value>
</param>
<param>
- <key>_rotation</key>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain10</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw10</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>dtv_dvbs2_physical_cc</key>
<param>
- <key>id</key>
- <value>dtv_dvbs2_physical_cc_0</value>
+ <key>corr10</key>
+ <value>0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>freq10</key>
+ <value>100e6</value>
</param>
<param>
- <key>framesize</key>
- <value>FECFRAME_NORMAL</value>
+ <key>if_gain10</key>
+ <value>20</value>
</param>
<param>
- <key>constellation</key>
- <value>MOD_16APSK</value>
+ <key>gain10</key>
+ <value>10</value>
</param>
<param>
- <key>rate</key>
- <value>C9_10</value>
+ <key>ant11</key>
+ <value></value>
</param>
<param>
- <key>pilots</key>
- <value>PILOTS_ON</value>
+ <key>bb_gain11</key>
+ <value>20</value>
</param>
<param>
- <key>goldcode</key>
+ <key>bw11</key>
<value>0</value>
</param>
<param>
- <key>alias</key>
- <value></value>
+ <key>corr11</key>
+ <value>0</value>
</param>
<param>
- <key>affinity</key>
+ <key>freq11</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain11</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant12</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
+ <key>bb_gain12</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw12</key>
<value>0</value>
</param>
<param>
- <key>maxoutbuf</key>
+ <key>corr12</key>
<value>0</value>
</param>
<param>
- <key>_coordinate</key>
- <value>(192, 443)</value>
+ <key>freq12</key>
+ <value>100e6</value>
</param>
<param>
- <key>_rotation</key>
+ <key>if_gain12</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain13</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw13</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>osmosdr_sink</key>
<param>
- <key>id</key>
- <value>osmosdr_sink_0</value>
+ <key>corr13</key>
+ <value>0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>freq13</key>
+ <value>100e6</value>
</param>
<param>
- <key>type</key>
- <value>fc32</value>
+ <key>if_gain13</key>
+ <value>20</value>
</param>
<param>
- <key>args</key>
- <value>bladerf=0,buffers=128,buflen=32768</value>
+ <key>gain13</key>
+ <value>10</value>
</param>
<param>
- <key>sync</key>
+ <key>ant14</key>
<value></value>
</param>
<param>
- <key>num_mboards</key>
- <value>1</value>
+ <key>bb_gain14</key>
+ <value>20</value>
</param>
<param>
- <key>clock_source0</key>
- <value></value>
+ <key>bw14</key>
+ <value>0</value>
</param>
<param>
- <key>time_source0</key>
- <value></value>
+ <key>corr14</key>
+ <value>0</value>
</param>
<param>
- <key>clock_source1</key>
- <value></value>
+ <key>freq14</key>
+ <value>100e6</value>
</param>
<param>
- <key>time_source1</key>
- <value></value>
+ <key>if_gain14</key>
+ <value>20</value>
</param>
<param>
- <key>clock_source2</key>
- <value></value>
+ <key>gain14</key>
+ <value>10</value>
</param>
<param>
- <key>time_source2</key>
+ <key>ant15</key>
<value></value>
</param>
<param>
- <key>clock_source3</key>
- <value></value>
+ <key>bb_gain15</key>
+ <value>20</value>
</param>
<param>
- <key>time_source3</key>
- <value></value>
+ <key>bw15</key>
+ <value>0</value>
</param>
<param>
- <key>clock_source4</key>
- <value></value>
+ <key>corr15</key>
+ <value>0</value>
</param>
<param>
- <key>time_source4</key>
- <value></value>
+ <key>freq15</key>
+ <value>100e6</value>
</param>
<param>
- <key>clock_source5</key>
- <value></value>
+ <key>if_gain15</key>
+ <value>20</value>
</param>
<param>
- <key>time_source5</key>
- <value></value>
+ <key>gain15</key>
+ <value>10</value>
</param>
<param>
- <key>clock_source6</key>
+ <key>ant16</key>
<value></value>
</param>
<param>
- <key>time_source6</key>
- <value></value>
+ <key>bb_gain16</key>
+ <value>20</value>
</param>
<param>
- <key>clock_source7</key>
- <value></value>
+ <key>bw16</key>
+ <value>0</value>
</param>
<param>
- <key>time_source7</key>
- <value></value>
+ <key>corr16</key>
+ <value>0</value>
</param>
<param>
- <key>nchan</key>
- <value>1</value>
+ <key>freq16</key>
+ <value>100e6</value>
</param>
<param>
- <key>sample_rate</key>
- <value>samp_rate</value>
+ <key>if_gain16</key>
+ <value>20</value>
</param>
<param>
- <key>freq0</key>
- <value>1280e6</value>
+ <key>gain16</key>
+ <value>10</value>
</param>
<param>
- <key>corr0</key>
- <value>0</value>
+ <key>ant17</key>
+ <value></value>
</param>
<param>
- <key>gain0</key>
- <value>15</value>
+ <key>bb_gain17</key>
+ <value>20</value>
</param>
<param>
- <key>if_gain0</key>
+ <key>bw17</key>
<value>0</value>
</param>
<param>
- <key>bb_gain0</key>
- <value>-10</value>
+ <key>corr17</key>
+ <value>0</value>
</param>
<param>
- <key>ant0</key>
+ <key>freq17</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain17</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant18</key>
<value></value>
</param>
<param>
- <key>bw0</key>
- <value>6000000</value>
+ <key>bb_gain18</key>
+ <value>20</value>
</param>
<param>
- <key>freq1</key>
- <value>100e6</value>
+ <key>bw18</key>
+ <value>0</value>
</param>
<param>
- <key>corr1</key>
+ <key>corr18</key>
<value>0</value>
</param>
<param>
- <key>gain1</key>
+ <key>freq18</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain18</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain18</key>
<value>10</value>
</param>
<param>
- <key>if_gain1</key>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain19</key>
<value>20</value>
</param>
<param>
- <key>bb_gain1</key>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq19</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain19</key>
<value>20</value>
</param>
<param>
+ <key>gain19</key>
+ <value>10</value>
+ </param>
+ <param>
<key>ant1</key>
<value></value>
</param>
<param>
+ <key>bb_gain1</key>
+ <value>20</value>
+ </param>
+ <param>
<key>bw1</key>
<value>0</value>
</param>
<param>
- <key>freq2</key>
+ <key>corr1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq1</key>
<value>100e6</value>
</param>
<param>
- <key>corr2</key>
- <value>0</value>
+ <key>if_gain1</key>
+ <value>20</value>
</param>
<param>
- <key>gain2</key>
+ <key>gain1</key>
<value>10</value>
</param>
<param>
- <key>if_gain2</key>
- <value>20</value>
+ <key>ant20</key>
+ <value></value>
</param>
<param>
- <key>bb_gain2</key>
+ <key>bb_gain20</key>
<value>20</value>
</param>
<param>
- <key>ant2</key>
- <value></value>
+ <key>bw20</key>
+ <value>0</value>
</param>
<param>
- <key>bw2</key>
+ <key>corr20</key>
<value>0</value>
</param>
<param>
- <key>freq3</key>
+ <key>freq20</key>
<value>100e6</value>
</param>
<param>
- <key>corr3</key>
- <value>0</value>
+ <key>if_gain20</key>
+ <value>20</value>
</param>
<param>
- <key>gain3</key>
+ <key>gain20</key>
<value>10</value>
</param>
<param>
- <key>if_gain3</key>
- <value>20</value>
+ <key>ant21</key>
+ <value></value>
</param>
<param>
- <key>bb_gain3</key>
+ <key>bb_gain21</key>
<value>20</value>
</param>
<param>
- <key>ant3</key>
- <value></value>
+ <key>bw21</key>
+ <value>0</value>
</param>
<param>
- <key>bw3</key>
+ <key>corr21</key>
<value>0</value>
</param>
<param>
- <key>freq4</key>
+ <key>freq21</key>
<value>100e6</value>
</param>
<param>
- <key>corr4</key>
- <value>0</value>
+ <key>if_gain21</key>
+ <value>20</value>
</param>
<param>
- <key>gain4</key>
+ <key>gain21</key>
<value>10</value>
</param>
<param>
- <key>if_gain4</key>
- <value>20</value>
+ <key>ant22</key>
+ <value></value>
</param>
<param>
- <key>bb_gain4</key>
+ <key>bb_gain22</key>
<value>20</value>
</param>
<param>
- <key>ant4</key>
- <value></value>
+ <key>bw22</key>
+ <value>0</value>
</param>
<param>
- <key>bw4</key>
+ <key>corr22</key>
<value>0</value>
</param>
<param>
- <key>freq5</key>
+ <key>freq22</key>
<value>100e6</value>
</param>
<param>
- <key>corr5</key>
- <value>0</value>
+ <key>if_gain22</key>
+ <value>20</value>
</param>
<param>
- <key>gain5</key>
+ <key>gain22</key>
<value>10</value>
</param>
<param>
- <key>if_gain5</key>
- <value>20</value>
+ <key>ant23</key>
+ <value></value>
</param>
<param>
- <key>bb_gain5</key>
+ <key>bb_gain23</key>
<value>20</value>
</param>
<param>
- <key>ant5</key>
- <value></value>
+ <key>bw23</key>
+ <value>0</value>
</param>
<param>
- <key>bw5</key>
+ <key>corr23</key>
<value>0</value>
</param>
<param>
- <key>freq6</key>
+ <key>freq23</key>
<value>100e6</value>
</param>
<param>
- <key>corr6</key>
- <value>0</value>
+ <key>if_gain23</key>
+ <value>20</value>
</param>
<param>
- <key>gain6</key>
+ <key>gain23</key>
<value>10</value>
</param>
<param>
- <key>if_gain6</key>
- <value>20</value>
+ <key>ant24</key>
+ <value></value>
</param>
<param>
- <key>bb_gain6</key>
+ <key>bb_gain24</key>
<value>20</value>
</param>
<param>
- <key>ant6</key>
- <value></value>
+ <key>bw24</key>
+ <value>0</value>
</param>
<param>
- <key>bw6</key>
+ <key>corr24</key>
<value>0</value>
</param>
<param>
- <key>freq7</key>
+ <key>freq24</key>
<value>100e6</value>
</param>
<param>
- <key>corr7</key>
- <value>0</value>
+ <key>if_gain24</key>
+ <value>20</value>
</param>
<param>
- <key>gain7</key>
+ <key>gain24</key>
<value>10</value>
</param>
<param>
- <key>if_gain7</key>
- <value>20</value>
+ <key>ant25</key>
+ <value></value>
</param>
<param>
- <key>bb_gain7</key>
+ <key>bb_gain25</key>
<value>20</value>
</param>
<param>
- <key>ant7</key>
- <value></value>
+ <key>bw25</key>
+ <value>0</value>
</param>
<param>
- <key>bw7</key>
+ <key>corr25</key>
<value>0</value>
</param>
<param>
- <key>freq8</key>
+ <key>freq25</key>
<value>100e6</value>
</param>
<param>
- <key>corr8</key>
- <value>0</value>
+ <key>if_gain25</key>
+ <value>20</value>
</param>
<param>
- <key>gain8</key>
+ <key>gain25</key>
<value>10</value>
</param>
<param>
- <key>if_gain8</key>
- <value>20</value>
+ <key>ant26</key>
+ <value></value>
</param>
<param>
- <key>bb_gain8</key>
+ <key>bb_gain26</key>
<value>20</value>
</param>
<param>
- <key>ant8</key>
- <value></value>
+ <key>bw26</key>
+ <value>0</value>
</param>
<param>
- <key>bw8</key>
+ <key>corr26</key>
<value>0</value>
</param>
<param>
- <key>freq9</key>
+ <key>freq26</key>
<value>100e6</value>
</param>
<param>
- <key>corr9</key>
- <value>0</value>
+ <key>if_gain26</key>
+ <value>20</value>
</param>
<param>
- <key>gain9</key>
+ <key>gain26</key>
<value>10</value>
</param>
<param>
- <key>if_gain9</key>
- <value>20</value>
+ <key>ant27</key>
+ <value></value>
</param>
<param>
- <key>bb_gain9</key>
+ <key>bb_gain27</key>
<value>20</value>
</param>
<param>
- <key>ant9</key>
- <value></value>
+ <key>bw27</key>
+ <value>0</value>
</param>
<param>
- <key>bw9</key>
+ <key>corr27</key>
<value>0</value>
</param>
<param>
- <key>freq10</key>
+ <key>freq27</key>
<value>100e6</value>
</param>
<param>
- <key>corr10</key>
- <value>0</value>
+ <key>if_gain27</key>
+ <value>20</value>
</param>
<param>
- <key>gain10</key>
+ <key>gain27</key>
<value>10</value>
</param>
<param>
- <key>if_gain10</key>
- <value>20</value>
+ <key>ant28</key>
+ <value></value>
</param>
<param>
- <key>bb_gain10</key>
+ <key>bb_gain28</key>
<value>20</value>
</param>
<param>
- <key>ant10</key>
- <value></value>
+ <key>bw28</key>
+ <value>0</value>
</param>
<param>
- <key>bw10</key>
+ <key>corr28</key>
<value>0</value>
</param>
<param>
- <key>freq11</key>
+ <key>freq28</key>
<value>100e6</value>
</param>
<param>
- <key>corr11</key>
- <value>0</value>
+ <key>if_gain28</key>
+ <value>20</value>
</param>
<param>
- <key>gain11</key>
+ <key>gain28</key>
<value>10</value>
</param>
<param>
- <key>if_gain11</key>
- <value>20</value>
+ <key>ant29</key>
+ <value></value>
</param>
<param>
- <key>bb_gain11</key>
+ <key>bb_gain29</key>
<value>20</value>
</param>
<param>
- <key>ant11</key>
- <value></value>
+ <key>bw29</key>
+ <value>0</value>
</param>
<param>
- <key>bw11</key>
+ <key>corr29</key>
<value>0</value>
</param>
<param>
- <key>freq12</key>
+ <key>freq29</key>
<value>100e6</value>
</param>
<param>
- <key>corr12</key>
- <value>0</value>
+ <key>if_gain29</key>
+ <value>20</value>
</param>
<param>
- <key>gain12</key>
+ <key>gain29</key>
<value>10</value>
</param>
<param>
- <key>if_gain12</key>
- <value>20</value>
+ <key>ant2</key>
+ <value></value>
</param>
<param>
- <key>bb_gain12</key>
+ <key>bb_gain2</key>
<value>20</value>
</param>
<param>
- <key>ant12</key>
- <value></value>
+ <key>bw2</key>
+ <value>0</value>
</param>
<param>
- <key>bw12</key>
+ <key>corr2</key>
<value>0</value>
</param>
<param>
- <key>freq13</key>
+ <key>freq2</key>
<value>100e6</value>
</param>
<param>
- <key>corr13</key>
- <value>0</value>
+ <key>if_gain2</key>
+ <value>20</value>
</param>
<param>
- <key>gain13</key>
+ <key>gain2</key>
<value>10</value>
</param>
<param>
- <key>if_gain13</key>
- <value>20</value>
+ <key>ant30</key>
+ <value></value>
</param>
<param>
- <key>bb_gain13</key>
+ <key>bb_gain30</key>
<value>20</value>
</param>
<param>
- <key>ant13</key>
- <value></value>
+ <key>bw30</key>
+ <value>0</value>
</param>
<param>
- <key>bw13</key>
+ <key>corr30</key>
<value>0</value>
</param>
<param>
- <key>freq14</key>
+ <key>freq30</key>
<value>100e6</value>
</param>
<param>
- <key>corr14</key>
- <value>0</value>
+ <key>if_gain30</key>
+ <value>20</value>
</param>
<param>
- <key>gain14</key>
+ <key>gain30</key>
<value>10</value>
</param>
<param>
- <key>if_gain14</key>
- <value>20</value>
+ <key>ant31</key>
+ <value></value>
</param>
<param>
- <key>bb_gain14</key>
+ <key>bb_gain31</key>
<value>20</value>
</param>
<param>
- <key>ant14</key>
- <value></value>
+ <key>bw31</key>
+ <value>0</value>
</param>
<param>
- <key>bw14</key>
+ <key>corr31</key>
<value>0</value>
</param>
<param>
- <key>freq15</key>
+ <key>freq31</key>
<value>100e6</value>
</param>
<param>
- <key>corr15</key>
- <value>0</value>
+ <key>if_gain31</key>
+ <value>20</value>
</param>
<param>
- <key>gain15</key>
+ <key>gain31</key>
<value>10</value>
</param>
<param>
- <key>if_gain15</key>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain3</key>
<value>20</value>
</param>
<param>
- <key>bb_gain15</key>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq3</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain3</key>
<value>20</value>
</param>
<param>
- <key>ant15</key>
+ <key>gain3</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant4</key>
<value></value>
</param>
<param>
- <key>bw15</key>
+ <key>bb_gain4</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw4</key>
<value>0</value>
</param>
<param>
- <key>freq16</key>
+ <key>corr4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq4</key>
<value>100e6</value>
</param>
<param>
- <key>corr16</key>
- <value>0</value>
+ <key>if_gain4</key>
+ <value>20</value>
</param>
<param>
- <key>gain16</key>
+ <key>gain4</key>
<value>10</value>
</param>
<param>
- <key>if_gain16</key>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain5</key>
<value>20</value>
</param>
<param>
- <key>bb_gain16</key>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq5</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain5</key>
<value>20</value>
</param>
<param>
- <key>ant16</key>
+ <key>gain5</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant6</key>
<value></value>
</param>
<param>
- <key>bw16</key>
+ <key>bb_gain6</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw6</key>
<value>0</value>
</param>
<param>
- <key>freq17</key>
+ <key>corr6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq6</key>
<value>100e6</value>
</param>
<param>
- <key>corr17</key>
- <value>0</value>
+ <key>if_gain6</key>
+ <value>20</value>
</param>
<param>
- <key>gain17</key>
+ <key>gain6</key>
<value>10</value>
</param>
<param>
- <key>if_gain17</key>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain7</key>
<value>20</value>
</param>
<param>
- <key>bb_gain17</key>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq7</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain7</key>
<value>20</value>
</param>
<param>
- <key>ant17</key>
+ <key>gain7</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant8</key>
<value></value>
</param>
<param>
- <key>bw17</key>
+ <key>bb_gain8</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw8</key>
<value>0</value>
</param>
<param>
- <key>freq18</key>
+ <key>corr8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq8</key>
<value>100e6</value>
</param>
<param>
- <key>corr18</key>
- <value>0</value>
+ <key>if_gain8</key>
+ <value>20</value>
</param>
<param>
- <key>gain18</key>
+ <key>gain8</key>
<value>10</value>
</param>
<param>
- <key>if_gain18</key>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain9</key>
<value>20</value>
</param>
<param>
- <key>bb_gain18</key>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq9</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain9</key>
<value>20</value>
</param>
<param>
- <key>ant18</key>
+ <key>gain9</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>comment</key>
<value></value>
</param>
<param>
- <key>bw18</key>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>args</key>
+ <value>bladerf=0,buffers=128,buflen=32768</value>
+ </param>
+ <param>
+ <key>_enabled</key>
<value>0</value>
</param>
<param>
- <key>freq19</key>
- <value>100e6</value>
+ <key>_coordinate</key>
+ <value>(1040, 243)</value>
</param>
<param>
- <key>corr19</key>
+ <key>_rotation</key>
<value>0</value>
</param>
<param>
- <key>gain19</key>
- <value>10</value>
+ <key>id</key>
+ <value>osmosdr_sink_0</value>
</param>
<param>
- <key>if_gain19</key>
- <value>20</value>
+ <key>type</key>
+ <value>fc32</value>
</param>
<param>
- <key>bb_gain19</key>
- <value>20</value>
+ <key>clock_source0</key>
+ <value></value>
</param>
<param>
- <key>ant19</key>
+ <key>time_source0</key>
<value></value>
</param>
<param>
- <key>bw19</key>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>sample_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_sink</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw0</key>
<value>0</value>
</param>
<param>
- <key>freq20</key>
- <value>100e6</value>
+ <key>center_freq0</key>
+ <value>uhd.tune_request(frequency, ((symbol_rate * (1 + rolloff)) / 2 ) + 1e5)</value>
</param>
<param>
- <key>corr20</key>
+ <key>norm_gain0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>60</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw10</key>
<value>0</value>
</param>
<param>
- <key>gain20</key>
- <value>10</value>
+ <key>center_freq10</key>
+ <value>0</value>
</param>
<param>
- <key>if_gain20</key>
- <value>20</value>
+ <key>norm_gain10</key>
+ <value>False</value>
</param>
<param>
- <key>bb_gain20</key>
- <value>20</value>
+ <key>gain10</key>
+ <value>0</value>
</param>
<param>
- <key>ant20</key>
+ <key>ant11</key>
<value></value>
</param>
<param>
- <key>bw20</key>
+ <key>bw11</key>
<value>0</value>
</param>
<param>
- <key>freq21</key>
- <value>100e6</value>
+ <key>center_freq11</key>
+ <value>0</value>
</param>
<param>
- <key>corr21</key>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain11</key>
<value>0</value>
</param>
<param>
- <key>gain21</key>
- <value>10</value>
+ <key>ant12</key>
+ <value></value>
</param>
<param>
- <key>if_gain21</key>
- <value>20</value>
+ <key>bw12</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain21</key>
- <value>20</value>
+ <key>center_freq12</key>
+ <value>0</value>
</param>
<param>
- <key>ant21</key>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant13</key>
<value></value>
</param>
<param>
- <key>bw21</key>
+ <key>bw13</key>
<value>0</value>
</param>
<param>
- <key>freq22</key>
- <value>100e6</value>
+ <key>center_freq13</key>
+ <value>0</value>
</param>
<param>
- <key>corr22</key>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain13</key>
<value>0</value>
</param>
<param>
- <key>gain22</key>
- <value>10</value>
+ <key>ant14</key>
+ <value></value>
</param>
<param>
- <key>if_gain22</key>
- <value>20</value>
+ <key>bw14</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain22</key>
- <value>20</value>
+ <key>center_freq14</key>
+ <value>0</value>
</param>
<param>
- <key>ant22</key>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant15</key>
<value></value>
</param>
<param>
- <key>bw22</key>
+ <key>bw15</key>
<value>0</value>
</param>
<param>
- <key>freq23</key>
- <value>100e6</value>
+ <key>center_freq15</key>
+ <value>0</value>
</param>
<param>
- <key>corr23</key>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain15</key>
<value>0</value>
</param>
<param>
- <key>gain23</key>
- <value>10</value>
+ <key>ant16</key>
+ <value></value>
</param>
<param>
- <key>if_gain23</key>
- <value>20</value>
+ <key>bw16</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain23</key>
- <value>20</value>
+ <key>center_freq16</key>
+ <value>0</value>
</param>
<param>
- <key>ant23</key>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant17</key>
<value></value>
</param>
<param>
- <key>bw23</key>
+ <key>bw17</key>
<value>0</value>
</param>
<param>
- <key>freq24</key>
- <value>100e6</value>
+ <key>center_freq17</key>
+ <value>0</value>
</param>
<param>
- <key>corr24</key>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain17</key>
<value>0</value>
</param>
<param>
- <key>gain24</key>
- <value>10</value>
+ <key>ant18</key>
+ <value></value>
</param>
<param>
- <key>if_gain24</key>
- <value>20</value>
+ <key>bw18</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain24</key>
- <value>20</value>
+ <key>center_freq18</key>
+ <value>0</value>
</param>
<param>
- <key>ant24</key>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant19</key>
<value></value>
</param>
<param>
- <key>bw24</key>
+ <key>bw19</key>
<value>0</value>
</param>
<param>
- <key>freq25</key>
- <value>100e6</value>
+ <key>center_freq19</key>
+ <value>0</value>
</param>
<param>
- <key>corr25</key>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain19</key>
<value>0</value>
</param>
<param>
- <key>gain25</key>
- <value>10</value>
+ <key>ant1</key>
+ <value></value>
</param>
<param>
- <key>if_gain25</key>
- <value>20</value>
+ <key>bw1</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain25</key>
- <value>20</value>
+ <key>center_freq1</key>
+ <value>0</value>
</param>
<param>
- <key>ant25</key>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant20</key>
<value></value>
</param>
<param>
- <key>bw25</key>
+ <key>bw20</key>
<value>0</value>
</param>
<param>
- <key>freq26</key>
- <value>100e6</value>
+ <key>center_freq20</key>
+ <value>0</value>
</param>
<param>
- <key>corr26</key>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain20</key>
<value>0</value>
</param>
<param>
- <key>gain26</key>
- <value>10</value>
+ <key>ant21</key>
+ <value></value>
</param>
<param>
- <key>if_gain26</key>
- <value>20</value>
+ <key>bw21</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain26</key>
- <value>20</value>
+ <key>center_freq21</key>
+ <value>0</value>
</param>
<param>
- <key>ant26</key>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant22</key>
<value></value>
</param>
<param>
- <key>bw26</key>
+ <key>bw22</key>
<value>0</value>
</param>
<param>
- <key>freq27</key>
- <value>100e6</value>
+ <key>center_freq22</key>
+ <value>0</value>
</param>
<param>
- <key>corr27</key>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain22</key>
<value>0</value>
</param>
<param>
- <key>gain27</key>
- <value>10</value>
+ <key>ant23</key>
+ <value></value>
</param>
<param>
- <key>if_gain27</key>
- <value>20</value>
+ <key>bw23</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain27</key>
- <value>20</value>
+ <key>center_freq23</key>
+ <value>0</value>
</param>
<param>
- <key>ant27</key>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant24</key>
<value></value>
</param>
<param>
- <key>bw27</key>
+ <key>bw24</key>
<value>0</value>
</param>
<param>
- <key>freq28</key>
- <value>100e6</value>
+ <key>center_freq24</key>
+ <value>0</value>
</param>
<param>
- <key>corr28</key>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain24</key>
<value>0</value>
</param>
<param>
- <key>gain28</key>
- <value>10</value>
+ <key>ant25</key>
+ <value></value>
</param>
<param>
- <key>if_gain28</key>
- <value>20</value>
+ <key>bw25</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain28</key>
- <value>20</value>
+ <key>center_freq25</key>
+ <value>0</value>
</param>
<param>
- <key>ant28</key>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant26</key>
<value></value>
</param>
<param>
- <key>bw28</key>
+ <key>bw26</key>
<value>0</value>
</param>
<param>
- <key>freq29</key>
- <value>100e6</value>
+ <key>center_freq26</key>
+ <value>0</value>
</param>
<param>
- <key>corr29</key>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain26</key>
<value>0</value>
</param>
<param>
- <key>gain29</key>
- <value>10</value>
+ <key>ant27</key>
+ <value></value>
</param>
<param>
- <key>if_gain29</key>
- <value>20</value>
+ <key>bw27</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain29</key>
- <value>20</value>
+ <key>center_freq27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>0</value>
</param>
<param>
<key>ant29</key>
@@ -1596,24 +2272,36 @@
<value>0</value>
</param>
<param>
- <key>freq30</key>
- <value>100e6</value>
+ <key>center_freq29</key>
+ <value>0</value>
</param>
<param>
- <key>corr30</key>
+ <key>norm_gain29</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain29</key>
<value>0</value>
</param>
<param>
- <key>gain30</key>
- <value>10</value>
+ <key>ant2</key>
+ <value></value>
</param>
<param>
- <key>if_gain30</key>
- <value>20</value>
+ <key>bw2</key>
+ <value>0</value>
</param>
<param>
- <key>bb_gain30</key>
- <value>20</value>
+ <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>
<key>ant30</key>
@@ -1624,82 +2312,183 @@
<value>0</value>
</param>
<param>
- <key>freq31</key>
- <value>100e6</value>
+ <key>center_freq30</key>
+ <value>0</value>
</param>
<param>
- <key>corr31</key>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain30</key>
<value>0</value>
</param>
<param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain31</key>
+ <value>False</value>
+ </param>
+ <param>
<key>gain31</key>
- <value>10</value>
+ <value>0</value>
</param>
<param>
- <key>if_gain31</key>
- <value>20</value>
+ <key>ant3</key>
+ <value></value>
</param>
<param>
- <key>bb_gain31</key>
- <value>20</value>
+ <key>bw3</key>
+ <value>0</value>
</param>
<param>
- <key>ant31</key>
+ <key>center_freq3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant4</key>
<value></value>
</param>
<param>
- <key>bw31</key>
+ <key>bw4</key>
<value>0</value>
</param>
<param>
- <key>alias</key>
+ <key>center_freq4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant5</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant6</key>
<value></value>
</param>
<param>
- <key>_coordinate</key>
- <value>(1000, 203)</value>
+ <key>bw6</key>
+ <value>0</value>
</param>
<param>
- <key>_rotation</key>
+ <key>center_freq6</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>blocks_file_sink</key>
<param>
- <key>id</key>
- <value>blocks_file_sink_0</value>
+ <key>norm_gain6</key>
+ <value>False</value>
</param>
<param>
- <key>_enabled</key>
+ <key>gain6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain7</key>
<value>False</value>
</param>
<param>
- <key>file</key>
- <value>adv.cfile</value>
+ <key>gain7</key>
+ <value>0</value>
</param>
<param>
- <key>type</key>
- <value>complex</value>
+ <key>ant8</key>
+ <value></value>
</param>
<param>
- <key>vlen</key>
- <value>1</value>
+ <key>bw8</key>
+ <value>0</value>
</param>
<param>
- <key>unbuffered</key>
+ <key>center_freq8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain8</key>
<value>False</value>
</param>
<param>
- <key>append</key>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain9</key>
<value>False</value>
</param>
<param>
- <key>alias</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>
@@ -1707,163 +2496,270 @@
<value></value>
</param>
<param>
+ <key>dev_addr</key>
+ <value>"send_frame_size=65536,num_send_frames=256,master_clock_rate=" + str(samp_rate*2)</value>
+ </param>
+ <param>
+ <key>dev_args</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
<key>_coordinate</key>
- <value>(792, 547)</value>
+ <value>(1040, 427)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
- </block>
- <block>
- <key>dtv_dvb_bbheader_bb</key>
<param>
<key>id</key>
- <value>dtv_dvb_bbheader_bb_0</value>
+ <value>uhd_usrp_sink_0_0</value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>type</key>
+ <value>fc32</value>
</param>
<param>
- <key>standard</key>
- <value>STANDARD_DVBS2</value>
+ <key>clock_source0</key>
+ <value></value>
</param>
<param>
- <key>framesize</key>
- <value>FECFRAME_NORMAL</value>
+ <key>sd_spec0</key>
+ <value></value>
</param>
<param>
- <key>rate1</key>
- <value>C1_2</value>
+ <key>time_source0</key>
+ <value></value>
</param>
<param>
- <key>rate2</key>
- <value>C1_3</value>
+ <key>clock_source1</key>
+ <value></value>
</param>
<param>
- <key>rate3</key>
- <value>C9_10</value>
+ <key>sd_spec1</key>
+ <value></value>
</param>
<param>
- <key>rate4</key>
- <value>C1_4</value>
+ <key>time_source1</key>
+ <value></value>
</param>
<param>
- <key>rolloff</key>
- <value>RO_0_20</value>
+ <key>clock_source2</key>
+ <value></value>
</param>
<param>
- <key>mode</key>
- <value>FECFRAME_NORMAL</value>
+ <key>sd_spec2</key>
+ <value></value>
</param>
<param>
- <key>inband</key>
- <value>INBAND_OFF</value>
+ <key>time_source2</key>
+ <value></value>
</param>
<param>
- <key>fecblocks</key>
- <value>168</value>
+ <key>clock_source3</key>
+ <value></value>
</param>
<param>
- <key>tsrate</key>
- <value>4000000</value>
+ <key>sd_spec3</key>
+ <value></value>
</param>
<param>
- <key>alias</key>
+ <key>time_source3</key>
<value></value>
</param>
<param>
- <key>affinity</key>
+ <key>clock_source4</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>sd_spec4</key>
+ <value></value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>time_source4</key>
+ <value></value>
</param>
<param>
- <key>_coordinate</key>
- <value>(400, 27)</value>
+ <key>clock_source5</key>
+ <value></value>
</param>
<param>
- <key>_rotation</key>
- <value>0</value>
+ <key>sd_spec5</key>
+ <value></value>
</param>
- </block>
- <block>
- <key>blocks_file_source</key>
<param>
- <key>id</key>
- <value>blocks_file_source_0</value>
+ <key>time_source5</key>
+ <value></value>
</param>
<param>
- <key>_enabled</key>
- <value>True</value>
+ <key>clock_source6</key>
+ <value></value>
</param>
<param>
- <key>file</key>
- <value>/run/shm/adv16apsk910.ts</value>
+ <key>sd_spec6</key>
+ <value></value>
</param>
<param>
- <key>type</key>
- <value>byte</value>
+ <key>time_source6</key>
+ <value></value>
</param>
<param>
- <key>repeat</key>
- <value>True</value>
+ <key>clock_source7</key>
+ <value></value>
</param>
<param>
- <key>vlen</key>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
<value>1</value>
</param>
<param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>hide_cmd_port</key>
+ <value>False</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>len_tag_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>avg_alpha</key>
+ <value>0.13333</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>frequency</value>
+ </param>
+ <param>
<key>alias</key>
<value></value>
</param>
<param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
<key>affinity</key>
<value></value>
</param>
<param>
- <key>minoutbuf</key>
- <value>0</value>
+ <key>_enabled</key>
+ <value>True</value>
</param>
<param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
</param>
<param>
<key>_coordinate</key>
- <value>(176, 43)</value>
+ <value>(784, 203)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
</block>
<connection>
- <source_block_id>fft_filter_xxx_0</source_block_id>
- <sink_block_id>osmosdr_sink_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>fft_filter_xxx_0</source_block_id>
- <sink_block_id>wxgui_fftsink2_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>fft_filter_xxx_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>blocks_file_source_0</source_block_id>
<sink_block_id>dtv_dvb_bbheader_bb_0</sink_block_id>
<source_key>0</source_key>
@@ -1900,14 +2796,38 @@
<sink_key>0</sink_key>
</connection>
<connection>
+ <source_block_id>dtv_dvbs2_modulator_bc_0</source_block_id>
+ <sink_block_id>dtv_dvbs2_physical_cc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
<source_block_id>dtv_dvbs2_physical_cc_0</source_block_id>
<sink_block_id>fft_filter_xxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
- <source_block_id>dtv_dvbs2_modulator_bc_0</source_block_id>
- <sink_block_id>dtv_dvbs2_physical_cc_0</sink_block_id>
+ <source_block_id>fft_filter_xxx_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>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>osmosdr_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>uhd_usrp_sink_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
diff --git a/gr-dtv/examples/dvbs_tx.grc b/gr-dtv/examples/dvbs_tx.grc
new file mode 100644
index 0000000000..c9dd98a0b9
--- /dev/null
+++ b/gr-dtv/examples/dvbs_tx.grc
@@ -0,0 +1,2853 @@
+<?xml version='1.0' encoding='utf-8'?>
+<?grc format='1' created='3.7.10'?>
+<flow_graph>
+ <timestamp>Wed Jun 18 01:23:58 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(8, 11)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>hier_block_src_path</key>
+ <value>.:</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dvbs_tx</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>qt_qss_theme</key>
+ <value></value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>run_command</key>
+ <value>{python} -u {filename}</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>thread_safe_setters</key>
+ <value></value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></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>(8, 203)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>frequency</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>1280e6</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>(8, 267)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>rrc_taps</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>100</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>(8, 75)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>symbol_rate * 2</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>(8, 139)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>symbol_rate</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>8000000</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_sink</key>
+ <param>
+ <key>append</key>
+ <value>False</value>
+ </param>
+ <param>
+ <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>0</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>adv.bin</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(848, 507)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_file_sink_0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>unbuffered</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_source</key>
+ <param>
+ <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>file</key>
+ <value>/run/shm/advdvbs78.ts</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(184, 59)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_file_source_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</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>
+ </block>
+ <block>
+ <key>blocks_pack_k_bits_bb</key>
+ <param>
+ <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>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(176, 451)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_pack_k_bits_bb_0</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_packed_to_unpacked_xx</key>
+ <param>
+ <key>bits_per_chunk</key>
+ <value>1</value>
+ </param>
+ <param>
+ <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>1</value>
+ </param>
+ <param>
+ <key>endianness</key>
+ <value>gr.GR_MSB_FIRST</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1080, 59)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_packed_to_unpacked_xx_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>num_ports</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_unpack_k_bits_bb</key>
+ <param>
+ <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>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(408, 235)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>blocks_unpack_k_bits_bb_0</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbs2_modulator_bc</key>
+ <param>
+ <key>interpolation</key>
+ <value>INTERPOLATION_ON</value>
+ </param>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>rate</key>
+ <value>C_OTHER</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>constellation</key>
+ <value>MOD_QPSK</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>framesize</key>
+ <value>FECFRAME_NORMAL</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(352, 427)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbs2_modulator_bc_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_convolutional_interleaver</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>136</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>M</key>
+ <value>17</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(832, 51)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_convolutional_interleaver_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>I</key>
+ <value>12</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_energy_dispersal</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nsize</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(408, 73)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_energy_dispersal_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>dtv_dvbt_reed_solomon_enc</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>blocks</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>gfpoly</key>
+ <value>0x11d</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(600, 19)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>dtv_dvbt_reed_solomon_enc_0</value>
+ </param>
+ <param>
+ <key>k</key>
+ <value>239</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>n</key>
+ <value>255</value>
+ </param>
+ <param>
+ <key>s</key>
+ <value>51</value>
+ </param>
+ <param>
+ <key>m</key>
+ <value>8</value>
+ </param>
+ <param>
+ <key>p</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>t</key>
+ <value>8</value>
+ </param>
+ </block>
+ <block>
+ <key>fec_puncture_xx</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(600, 219)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>fec_puncture_xx_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>puncpat</key>
+ <value>0b11010101100110</value>
+ </param>
+ <param>
+ <key>puncsize</key>
+ <value>14</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>byte</value>
+ </param>
+ </block>
+ <block>
+ <key>fft_filter_xxx</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>decim</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(584, 435)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>fft_filter_xxx_0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>nthreads</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_delay</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>taps</key>
+ <value>firdes.root_raised_cosine(1.0, samp_rate, samp_rate/2, 0.35, rrc_taps)</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>ccc</value>
+ </param>
+ </block>
+ <block>
+ <key>osmosdr_sink</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain0</key>
+ <value>-10</value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>10000000</value>
+ </param>
+ <param>
+ <key>corr0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq0</key>
+ <value>frequency</value>
+ </param>
+ <param>
+ <key>if_gain0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain10</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq10</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain10</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain11</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq11</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain11</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain12</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq12</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain12</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain13</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq13</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain13</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain14</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq14</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain14</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain15</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq15</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain15</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain16</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq16</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain16</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain17</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq17</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain17</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain18</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq18</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain18</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain19</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq19</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain19</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain1</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq1</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain1</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain20</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq20</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain20</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain21</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq21</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain21</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain22</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq22</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain22</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain23</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq23</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain23</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain24</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq24</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain24</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain25</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq25</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain25</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain26</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq26</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain26</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain27</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq27</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain27</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain28</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq28</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain28</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain29</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq29</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain29</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain29</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain2</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr2</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq2</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain2</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain2</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain30</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq30</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain30</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain31</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq31</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain31</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain31</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain3</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq3</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain3</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain4</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq4</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain4</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain5</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq5</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain5</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain6</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq6</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain6</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain7</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq7</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain7</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain8</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq8</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain8</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bb_gain9</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>corr9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>freq9</key>
+ <value>100e6</value>
+ </param>
+ <param>
+ <key>if_gain9</key>
+ <value>20</value>
+ </param>
+ <param>
+ <key>gain9</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>args</key>
+ <value>bladerf=0,buffers=128,buflen=32768</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1064, 211)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>osmosdr_sink_0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>sample_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>sync</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>trellis_encoder_xx</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>blocklength</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>blockwise</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>comment</key>
+ <value></value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>fsm_args</key>
+ <value>1, 2, (0171, 0133)</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(176, 227)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>trellis_encoder_xx_0</value>
+ </param>
+ <param>
+ <key>init_state</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>bb</value>
+ </param>
+ </block>
+ <block>
+ <key>uhd_usrp_sink</key>
+ <param>
+ <key>alias</key>
+ <value></value>
+ </param>
+ <param>
+ <key>ant0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw0</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq0</key>
+ <value>uhd.tune_request(frequency, ((symbol_rate * 1.35) / 2 ) + 1e5)</value>
+ </param>
+ <param>
+ <key>norm_gain0</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain0</key>
+ <value>60</value>
+ </param>
+ <param>
+ <key>ant10</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain10</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain10</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant11</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain11</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain11</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant12</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain12</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain12</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant13</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain13</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain13</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant14</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain14</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain14</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant15</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain15</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain15</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant16</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain16</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain16</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant17</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain17</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain17</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant18</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain18</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain18</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant19</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain19</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain19</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain1</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain1</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant20</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain20</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain20</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant21</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain21</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain21</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant22</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain22</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain22</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant23</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain23</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain23</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant24</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain24</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain24</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant25</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain25</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain25</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant26</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain26</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain26</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant27</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain27</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain27</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant28</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain28</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain28</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant29</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq29</key>
+ <value>0</value>
+ </param>
+ <param>
+ <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>
+ <key>ant30</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain30</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain30</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant31</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq31</key>
+ <value>0</value>
+ </param>
+ <param>
+ <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>bw3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain3</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain3</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain4</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain4</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain5</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain5</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain6</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain6</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain7</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain7</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant8</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain8</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>gain8</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ant9</key>
+ <value></value>
+ </param>
+ <param>
+ <key>bw9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>center_freq9</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>norm_gain9</key>
+ <value>False</value>
+ </param>
+ <param>
+ <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>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>dev_addr</key>
+ <value>"send_frame_size=65536,num_send_frames=256,master_clock_rate=" + str(samp_rate*2)</value>
+ </param>
+ <param>
+ <key>dev_args</key>
+ <value>""</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1064, 403)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>uhd_usrp_sink_0_0</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>fc32</value>
+ </param>
+ <param>
+ <key>clock_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source0</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source1</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source2</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source3</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source4</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source5</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source6</key>
+ <value></value>
+ </param>
+ <param>
+ <key>clock_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>sd_spec7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>time_source7</key>
+ <value></value>
+ </param>
+ <param>
+ <key>nchan</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>num_mboards</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>hide_cmd_port</key>
+ <value>False</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>len_tag_name</key>
+ <value></value>
+ </param>
+ <param>
+ <key>otw</key>
+ <value></value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>avg_alpha</key>
+ <value>0.13333</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>frequency</value>
+ </param>
+ <param>
+ <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>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(848, 195)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ </block>
+ <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>blocks_pack_k_bits_bb_0</source_block_id>
+ <sink_block_id>dtv_dvbs2_modulator_bc_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_packed_to_unpacked_xx_0</source_block_id>
+ <sink_block_id>trellis_encoder_xx_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>fec_puncture_xx_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>dtv_dvbs2_modulator_bc_0</source_block_id>
+ <sink_block_id>fft_filter_xxx_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>blocks_packed_to_unpacked_xx_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_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>
+ <connection>
+ <source_block_id>fec_puncture_xx_0</source_block_id>
+ <sink_block_id>blocks_pack_k_bits_bb_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_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>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>osmosdr_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>uhd_usrp_sink_0_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>fft_filter_xxx_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>trellis_encoder_xx_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>
+</flow_graph>
diff --git a/gr-dtv/grc/CMakeLists.txt b/gr-dtv/grc/CMakeLists.txt
index 2fed81ab12..a1386c5adf 100644
--- a/gr-dtv/grc/CMakeLists.txt
+++ b/gr-dtv/grc/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2014,2015 Free Software Foundation, Inc.
+# Copyright 2014,2015,2016 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -68,6 +68,11 @@ install(FILES
dtv_dvbt_convolutional_deinterleaver.xml
dtv_dvbt_reed_solomon_dec.xml
dtv_dvbt_energy_descramble.xml
+ dtv_catv_transport_framing_enc_bb.xml
+ dtv_catv_reed_solomon_enc_bb.xml
+ dtv_catv_randomizer_bb.xml
+ dtv_catv_frame_sync_enc_bb.xml
+ dtv_catv_trellis_enc_bb.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 32c8974531..fba33852c0 100644
--- a/gr-dtv/grc/dtv_block_tree.xml
+++ b/gr-dtv/grc/dtv_block_tree.xml
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<!--
- Copyright 2014,2015 Free Software Foundation, Inc.
+ Copyright 2014,2015,2016 Free Software Foundation, Inc.
This file is part of GNU Radio
@@ -94,5 +94,13 @@
<block>dtv_dvbt_reed_solomon_dec</block>
<block>dtv_dvbt_energy_descramble</block>
</cat>
+ <cat>
+ <name>ITU-T J.83B</name>
+ <block>dtv_catv_transport_framing_enc_bb</block>
+ <block>dtv_catv_reed_solomon_enc_bb</block>
+ <block>dtv_catv_randomizer_bb</block>
+ <block>dtv_catv_frame_sync_enc_bb</block>
+ <block>dtv_catv_trellis_enc_bb</block>
+ </cat>
</cat>
</cat>
diff --git a/gr-dtv/grc/dtv_catv_frame_sync_enc_bb.xml b/gr-dtv/grc/dtv_catv_frame_sync_enc_bb.xml
new file mode 100644
index 0000000000..e7c1392960
--- /dev/null
+++ b/gr-dtv/grc/dtv_catv_frame_sync_enc_bb.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Frame Sync Encoder
+###################################################
+ -->
+<block>
+ <name>Frame Sync Encoder</name>
+ <key>dtv_catv_frame_sync_enc_bb</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.catv_frame_sync_enc_bb($ctrlword)</make>
+ <param>
+ <name>Control Word</name>
+ <key>ctrlword</key>
+ <value>6</value>
+ <type>int</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_catv_randomizer_bb.xml b/gr-dtv/grc/dtv_catv_randomizer_bb.xml
new file mode 100644
index 0000000000..ca4787d786
--- /dev/null
+++ b/gr-dtv/grc/dtv_catv_randomizer_bb.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Randomizer
+###################################################
+ -->
+<block>
+ <name>Randomizer</name>
+ <key>dtv_catv_randomizer_bb</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.catv_randomizer_bb()</make>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_catv_reed_solomon_enc_bb.xml b/gr-dtv/grc/dtv_catv_reed_solomon_enc_bb.xml
new file mode 100644
index 0000000000..a5dfdc2a5a
--- /dev/null
+++ b/gr-dtv/grc/dtv_catv_reed_solomon_enc_bb.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Reed Solomon Encoder
+###################################################
+ -->
+<block>
+ <name>Reed-Solomon Encoder</name>
+ <key>dtv_catv_reed_solomon_enc_bb</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.catv_reed_solomon_enc_bb()</make>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_catv_transport_framing_enc_bb.xml b/gr-dtv/grc/dtv_catv_transport_framing_enc_bb.xml
new file mode 100644
index 0000000000..d0b6bf382b
--- /dev/null
+++ b/gr-dtv/grc/dtv_catv_transport_framing_enc_bb.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Transport Framing Encoder
+###################################################
+ -->
+<block>
+ <name>Transport Framing Encoder</name>
+ <key>dtv_catv_transport_framing_enc_bb</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.catv_transport_framing_enc_bb()</make>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_catv_trellis_enc_bb.xml b/gr-dtv/grc/dtv_catv_trellis_enc_bb.xml
new file mode 100644
index 0000000000..a96d60c895
--- /dev/null
+++ b/gr-dtv/grc/dtv_catv_trellis_enc_bb.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+## Trellis Encoder
+###################################################
+ -->
+<block>
+ <name>Trellis Encoder</name>
+ <key>dtv_catv_trellis_enc_bb</key>
+ <import>from gnuradio import dtv</import>
+ <make>dtv.catv_trellis_enc_bb()</make>
+ <sink>
+ <name>in</name>
+ <type>byte</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>byte</type>
+ </source>
+</block>
diff --git a/gr-dtv/grc/dtv_dvbs2_modulator_bc.xml b/gr-dtv/grc/dtv_dvbs2_modulator_bc.xml
index 1f7fef09a3..8de645d585 100644
--- a/gr-dtv/grc/dtv_dvbs2_modulator_bc.xml
+++ b/gr-dtv/grc/dtv_dvbs2_modulator_bc.xml
@@ -8,7 +8,7 @@
<name>DVB-S2X Modulator</name>
<key>dtv_dvbs2_modulator_bc</key>
<import>from gnuradio import dtv</import>
- <make>dtv.dvbs2_modulator_bc($framesize.val, $rate.val, $constellation.val)</make>
+ <make>dtv.dvbs2_modulator_bc($framesize.val, $rate.val, $constellation.val, $interpolation.val)</make>
<param>
<name>FECFRAME size</name>
<key>framesize</key>
@@ -253,6 +253,26 @@
<key>MOD_256APSK</key>
<opt>val:dtv.MOD_256APSK</opt>
</option>
+ <option>
+ <name>64QAM</name>
+ <key>MOD_64QAM</key>
+ <opt>val:dtv.MOD_64QAM</opt>
+ </option>
+ </param>
+ <param>
+ <name>2X Interpolation</name>
+ <key>interpolation</key>
+ <type>enum</type>
+ <option>
+ <name>Off</name>
+ <key>INTERPOLATION_OFF</key>
+ <opt>val:dtv.INTERPOLATION_OFF</opt>
+ </option>
+ <option>
+ <name>On</name>
+ <key>INTERPOLATION_ON</key>
+ <opt>val:dtv.INTERPOLATION_ON</opt>
+ </option>
</param>
<sink>
<name>in</name>
diff --git a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
index 4232ff7065..620dd55879 100644
--- a/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
+++ b/gr-dtv/include/gnuradio/dtv/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2014,2015 Free Software Foundation, Inc.
+# Copyright 2014,2015,2016 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -74,6 +74,11 @@ install(FILES
dvbt_convolutional_deinterleaver.h
dvbt_reed_solomon_dec.h
dvbt_energy_descramble.h
+ catv_transport_framing_enc_bb.h
+ catv_reed_solomon_enc_bb.h
+ catv_randomizer_bb.h
+ catv_frame_sync_enc_bb.h
+ catv_trellis_enc_bb.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/dtv
COMPONENT "dtv_devel"
diff --git a/gr-dtv/include/gnuradio/dtv/atsc_equalizer.h b/gr-dtv/include/gnuradio/dtv/atsc_equalizer.h
index 3fe101ac25..17f2e8f768 100644
--- a/gr-dtv/include/gnuradio/dtv/atsc_equalizer.h
+++ b/gr-dtv/include/gnuradio/dtv/atsc_equalizer.h
@@ -45,6 +45,9 @@ namespace gr {
* \brief Make a new instance of gr::dtv::atsc_equalizer.
*/
static sptr make();
+
+ virtual std::vector<float> taps() const = 0;
+ virtual std::vector<float> data() const = 0;
};
} /* namespace dtv */
diff --git a/gr-dtv/include/gnuradio/dtv/atsc_rs_decoder.h b/gr-dtv/include/gnuradio/dtv/atsc_rs_decoder.h
index 92eb263e5d..c2b7d0defa 100644
--- a/gr-dtv/include/gnuradio/dtv/atsc_rs_decoder.h
+++ b/gr-dtv/include/gnuradio/dtv/atsc_rs_decoder.h
@@ -42,6 +42,21 @@ namespace gr {
typedef boost::shared_ptr<atsc_rs_decoder> sptr;
/*!
+ * Returns the number of errors corrected by the decoder.
+ */
+ virtual int num_errors_corrected() const = 0;
+
+ /*!
+ * Returns the number of bad packets rejected by the decoder.
+ */
+ virtual int num_bad_packets() const = 0;
+
+ /*!
+ * Returns the total number of packets seen by the decoder.
+ */
+ virtual int num_packets() const = 0;
+
+ /*!
* \brief Make a new instance of gr::dtv::atsc_rs_decoder.
*/
static sptr make();
diff --git a/gr-dtv/include/gnuradio/dtv/atsc_viterbi_decoder.h b/gr-dtv/include/gnuradio/dtv/atsc_viterbi_decoder.h
index a4c18c39da..8efece4c43 100644
--- a/gr-dtv/include/gnuradio/dtv/atsc_viterbi_decoder.h
+++ b/gr-dtv/include/gnuradio/dtv/atsc_viterbi_decoder.h
@@ -45,6 +45,12 @@ namespace gr {
* \brief Make a new instance of gr::dtv::atsc_viterbi_decoder.
*/
static sptr make();
+
+ /*!
+ * For each decoder, returns the current best state of the
+ * decoding metrics.
+ */
+ virtual std::vector<float> decoder_metrics() const = 0;
};
} /* namespace dtv */
diff --git a/gr-dtv/include/gnuradio/dtv/catv_frame_sync_enc_bb.h b/gr-dtv/include/gnuradio/dtv/catv_frame_sync_enc_bb.h
new file mode 100644
index 0000000000..799a2d3c55
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/catv_frame_sync_enc_bb.h
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_FRAME_SYNC_ENC_BB_H
+#define INCLUDED_DTV_CATV_FRAME_SYNC_ENC_BB_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Frame Sync Encoder. Adds a 42-bit frame sync pattern with control word.
+ * \ingroup dtv
+ *
+ * Input: Scrambled FEC Frame packets of 60 * 128 7-bit symbols.\n
+ * Output: Scrambled FEC Frame packets of 60 * 128 7-bit symbols with 42-bit FSYNC word.
+ */
+ class DTV_API catv_frame_sync_enc_bb : virtual public gr::block
+ {
+ public:
+ typedef boost::shared_ptr<catv_frame_sync_enc_bb> sptr;
+
+ /*!
+ * \brief Create an ITU-T J.83B Frame Sync Encoder.
+ *
+ * \param ctrlword convolutional interleaver control word.
+ */
+ static sptr make(int ctrlword);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_CATV_FRAME_SYNC_ENC_BB_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/catv_randomizer_bb.h b/gr-dtv/include/gnuradio/dtv/catv_randomizer_bb.h
new file mode 100644
index 0000000000..83230b8167
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/catv_randomizer_bb.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_RANDOMIZER_BB_H
+#define INCLUDED_DTV_CATV_RANDOMIZER_BB_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Randomizer, x^3 + x + alpha^3, 7-bit symbols.
+ * \ingroup dtv
+ *
+ * Input: Interleaved MPEG-2 + RS parity bitstream packets of 128 7-bit symbols.\n
+ * Output: Scrambled FEC Frame packets of 60 * 128 7-bit symbols.
+ */
+ class DTV_API catv_randomizer_bb : virtual public gr::sync_block
+ {
+ public:
+ typedef boost::shared_ptr<catv_randomizer_bb> sptr;
+
+ /*!
+ * \brief Create an ITU-T J.83B randomizer.
+ *
+ */
+ static sptr make();
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_CATV_RANDOMIZER_BB_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/catv_reed_solomon_enc_bb.h b/gr-dtv/include/gnuradio/dtv/catv_reed_solomon_enc_bb.h
new file mode 100644
index 0000000000..b661f0da7f
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/catv_reed_solomon_enc_bb.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_REED_SOLOMON_ENC_BB_H
+#define INCLUDED_DTV_CATV_REED_SOLOMON_ENC_BB_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Reed Solomon Encoder, t=3, (128,122), 7-bit symbols.
+ * \ingroup dtv
+ *
+ * Input: MPEG-2 bitstream packets of 122 7-bit symbols.\n
+ * Output: MPEG-2 + RS parity bitstream packets of 128 7-bit symbols.
+ */
+ class DTV_API catv_reed_solomon_enc_bb : virtual public gr::block
+ {
+ public:
+ typedef boost::shared_ptr<catv_reed_solomon_enc_bb> sptr;
+
+ /*!
+ * \brief Create an ITU-T J.83B Reed Solomon encoder.
+ *
+ */
+ static sptr make();
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_CATV_REED_SOLOMON_ENC_BB_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/catv_transport_framing_enc_bb.h b/gr-dtv/include/gnuradio/dtv/catv_transport_framing_enc_bb.h
new file mode 100644
index 0000000000..7df100d990
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/catv_transport_framing_enc_bb.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_TRANSPORT_FRAMING_ENC_BB_H
+#define INCLUDED_DTV_CATV_TRANSPORT_FRAMING_ENC_BB_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Transport Framing Encoder. Adds a parity checksum to MPEG-2 packets.
+ * \ingroup dtv
+ *
+ * Input: MPEG-2 Transport Stream.\n
+ * Output: MPEG-2 Transport Stream with parity checksum byte.
+ */
+ class DTV_API catv_transport_framing_enc_bb : virtual public gr::sync_block
+ {
+ public:
+ typedef boost::shared_ptr<catv_transport_framing_enc_bb> sptr;
+
+ /*!
+ * \brief Create an ITU-T J.83B Transport Framing Encoder.
+ *
+ */
+ static sptr make();
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_CATV_TRANSPORT_FRAMING_ENC_BB_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/catv_trellis_enc_bb.h b/gr-dtv/include/gnuradio/dtv/catv_trellis_enc_bb.h
new file mode 100644
index 0000000000..aa6cec1703
--- /dev/null
+++ b/gr-dtv/include/gnuradio/dtv/catv_trellis_enc_bb.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_TRELLIS_ENC_BB_H
+#define INCLUDED_DTV_CATV_TRELLIS_ENC_BB_H
+
+#include <gnuradio/dtv/api.h>
+#include <gnuradio/block.h>
+
+namespace gr {
+ namespace dtv {
+
+ /*!
+ * \brief Trellis Encoder. 14/15 code rate.
+ * \ingroup dtv
+ *
+ * Input: Scrambled FEC Frame packets of 60 * 128 7-bit symbols with 42-bit FSYNC word.\n
+ * Output: Four 7-bit symbols (28 bits) Trellis encoded to 30 bits (14/15 code rate).
+ */
+ class DTV_API catv_trellis_enc_bb : virtual public gr::block
+ {
+ public:
+ typedef boost::shared_ptr<catv_trellis_enc_bb> sptr;
+
+ /*!
+ * \brief Create an ITU-T J.83B Trellis Encoder.
+ *
+ */
+ static sptr make();
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_CATV_TRELLIS_ENC_BB_H */
+
diff --git a/gr-dtv/include/gnuradio/dtv/dvbs2_config.h b/gr-dtv/include/gnuradio/dtv/dvbs2_config.h
index 919c7de155..079857a8cf 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbs2_config.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbs2_config.h
@@ -38,11 +38,17 @@ namespace gr {
PILOTS_ON,
};
+ enum dvbs2_interpolation_t {
+ INTERPOLATION_OFF = 0,
+ INTERPOLATION_ON,
+ };
+
} // namespace dtv
} // namespace gr
typedef gr::dtv::dvbs2_rolloff_factor_t dvbs2_rolloff_factor_t;
typedef gr::dtv::dvbs2_pilots_t dvbs2_pilots_t;
+typedef gr::dtv::dvbs2_interpolation_t dvbs2_interpolation_t;
#endif /* INCLUDED_DTV_DVBS2_CONFIG_H */
diff --git a/gr-dtv/include/gnuradio/dtv/dvbs2_modulator_bc.h b/gr-dtv/include/gnuradio/dtv/dvbs2_modulator_bc.h
index 68e5403e05..a1f2c9e6fe 100644
--- a/gr-dtv/include/gnuradio/dtv/dvbs2_modulator_bc.h
+++ b/gr-dtv/include/gnuradio/dtv/dvbs2_modulator_bc.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2015 Free Software Foundation, Inc.
+ * Copyright 2015,2016 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
@@ -23,6 +23,7 @@
#include <gnuradio/dtv/api.h>
#include <gnuradio/dtv/dvb_config.h>
+#include <gnuradio/dtv/dvbs2_config.h>
#include <gnuradio/block.h>
namespace gr {
@@ -46,8 +47,9 @@ namespace gr {
* \param framesize FEC frame size (normal or short).
* \param rate FEC code rate.
* \param constellation DVB-S2 constellation.
+ * \param interpolation 2X zero stuffing interpolation (on/off).
*/
- static sptr make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation);
+ static sptr make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbs2_interpolation_t interpolation);
};
} // namespace dtv
diff --git a/gr-dtv/lib/CMakeLists.txt b/gr-dtv/lib/CMakeLists.txt
index 868205c241..6ae308395d 100644
--- a/gr-dtv/lib/CMakeLists.txt
+++ b/gr-dtv/lib/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2014,2015 Free Software Foundation, Inc.
+# Copyright 2014,2015,2016 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -112,6 +112,11 @@ list(APPEND dtv_sources
dvbt/dvbt_convolutional_deinterleaver_impl.cc
dvbt/dvbt_reed_solomon_dec_impl.cc
dvbt/dvbt_energy_descramble_impl.cc
+ catv/catv_transport_framing_enc_bb_impl.cc
+ catv/catv_reed_solomon_enc_bb_impl.cc
+ catv/catv_randomizer_bb_impl.cc
+ catv/catv_frame_sync_enc_bb_impl.cc
+ catv/catv_trellis_enc_bb_impl.cc
)
if(ENABLE_GR_CTRLPORT)
diff --git a/gr-dtv/lib/atsc/atsc_equalizer_impl.cc b/gr-dtv/lib/atsc/atsc_equalizer_impl.cc
index c804be6dc7..de01cea6f2 100644
--- a/gr-dtv/lib/atsc/atsc_equalizer_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_equalizer_impl.cc
@@ -28,6 +28,7 @@
#include "atsc_types.h"
#include "atsc_pnXXX_impl.h"
#include <gnuradio/io_signature.h>
+#include <volk/volk.h>
namespace gr {
namespace dtv {
@@ -76,23 +77,42 @@ namespace gr {
init_field_sync_common(training_sequence1, 0);
init_field_sync_common(training_sequence2, 1);
- for (int i = 0; i < NTAPS; i++)
- d_taps[i] = 0.0;
+ d_taps.resize(NTAPS, 0.0f);
d_buff_not_filled = true;
+
+ const int alignment_multiple =
+ volk_get_alignment() / sizeof(float);
+ set_alignment(std::max(1, alignment_multiple));
}
atsc_equalizer_impl::~atsc_equalizer_impl()
{
}
+ std::vector<float>
+ atsc_equalizer_impl::taps() const
+ {
+ return d_taps;
+ }
+
+ std::vector<float>
+ atsc_equalizer_impl::data() const
+ {
+ std::vector<float> ret(&data_mem2[0], &data_mem2[ATSC_DATA_SEGMENT_LENGTH-1]);
+ return ret;
+ }
+
void
- atsc_equalizer_impl::filterN(const float *input_samples, float *output_samples, int nsamples)
+ atsc_equalizer_impl::filterN(const float *input_samples,
+ float *output_samples,
+ int nsamples)
{
for (int j = 0; j < nsamples; j++) {
output_samples[j] = 0;
- for(int i = 0; i < NTAPS; i++)
- output_samples[j] += d_taps[i] * input_samples[j + i];
+ volk_32f_x2_dot_prod_32f(&output_samples[j],
+ &input_samples[j],
+ &d_taps[0], NTAPS);
}
}
@@ -107,14 +127,16 @@ namespace gr {
for(int j = 0; j < nsamples; j++) {
output_samples[j] = 0;
- for( int i = 0; i < NTAPS; i++ )
- output_samples[j] += d_taps[i] * input_samples[j + i];
+ volk_32f_x2_dot_prod_32f(&output_samples[j],
+ &input_samples[j],
+ &d_taps[0], NTAPS);
- double e = output_samples[j] - training_pattern[j];
+ float e = output_samples[j] - training_pattern[j];
// update taps...
- for( int i = 0; i < NTAPS; i++ )
- d_taps[i] -= BETA * e * (double)(input_samples[j + i]);
+ float tmp_taps[NTAPS];
+ volk_32f_s32f_multiply_32f(tmp_taps, &input_samples[j], BETA*e, NTAPS);
+ volk_32f_x2_subtract_32f(&d_taps[0], &d_taps[0], tmp_taps, NTAPS);
}
}
@@ -131,8 +153,8 @@ namespace gr {
int i = 0;
if(d_buff_not_filled) {
- for(int j = 0; j < ATSC_DATA_SEGMENT_LENGTH; j++)
- data_mem[NPRETAPS + j] = in[i].data[j];
+ memcpy(&data_mem[NPRETAPS], in[i].data,
+ ATSC_DATA_SEGMENT_LENGTH*sizeof(float));
d_flags = in[i].pli._flags;
d_segno = in[i].pli._segno;
d_buff_not_filled = false;
@@ -141,8 +163,8 @@ namespace gr {
for (; i < noutput_items; i++) {
- for(int j = 0; j < NTAPS - NPRETAPS; j++)
- data_mem[ATSC_DATA_SEGMENT_LENGTH + NPRETAPS + j] = in[i].data[j];
+ memcpy(&data_mem[ATSC_DATA_SEGMENT_LENGTH + NPRETAPS], in[i].data,
+ (NTAPS - NPRETAPS)*sizeof(float));
if(d_segno == -1) {
if(d_flags & 0x0010) {
@@ -157,19 +179,18 @@ namespace gr {
else {
filterN(data_mem, data_mem2, ATSC_DATA_SEGMENT_LENGTH);
- for(int j = 0; j < ATSC_DATA_SEGMENT_LENGTH; j++)
- out[output_produced].data[j] = data_mem2[j];
+ memcpy(out[output_produced].data, data_mem2,
+ ATSC_DATA_SEGMENT_LENGTH*sizeof(float));
out[output_produced].pli._flags = d_flags;
out[output_produced].pli._segno = d_segno;
output_produced++;
}
- for( int j = 0; j < NPRETAPS; j++ )
- data_mem[j] = data_mem[ATSC_DATA_SEGMENT_LENGTH + j];
-
- for(int j = 0; j < ATSC_DATA_SEGMENT_LENGTH; j++)
- data_mem[NPRETAPS + j] = in[i].data[j];
+ memcpy(data_mem, &data_mem[ATSC_DATA_SEGMENT_LENGTH],
+ NPRETAPS*sizeof(float));
+ memcpy(&data_mem[NPRETAPS], in[i].data,
+ ATSC_DATA_SEGMENT_LENGTH*sizeof(float));
d_flags = in[i].pli._flags;
d_segno = in[i].pli._segno;
@@ -179,5 +200,31 @@ namespace gr {
return output_produced;
}
+ void
+ atsc_equalizer_impl::setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<atsc_equalizer, std::vector<float> >(
+ alias(), "taps",
+ &atsc_equalizer::taps,
+ pmt::make_f32vector(1,-10),
+ pmt::make_f32vector(1,10),
+ pmt::make_f32vector(1,0),
+ "", "Equalizer Taps", RPC_PRIVLVL_MIN,
+ DISPTIME)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<atsc_equalizer, std::vector<float> >(
+ alias(), "data",
+ &atsc_equalizer::data,
+ pmt::make_f32vector(1,-10),
+ pmt::make_f32vector(1,10),
+ pmt::make_f32vector(1,0),
+ "", "Post-equalizer Data", RPC_PRIVLVL_MIN,
+ DISPTIME)));
+#endif /* GR_CTRLPORT */
+ }
+
} /* namespace dtv */
} /* namespace gr */
diff --git a/gr-dtv/lib/atsc/atsc_equalizer_impl.h b/gr-dtv/lib/atsc/atsc_equalizer_impl.h
index 6ff89ca646..75862f6408 100644
--- a/gr-dtv/lib/atsc/atsc_equalizer_impl.h
+++ b/gr-dtv/lib/atsc/atsc_equalizer_impl.h
@@ -46,7 +46,7 @@ namespace gr {
void adaptN(const float *input_samples, const float *training_pattern,
float *output_samples, int nsamples);
- float d_taps[NTAPS];
+ std::vector<float> d_taps;
float data_mem[ATSC_DATA_SEGMENT_LENGTH + NTAPS]; // Buffer for previous data packet
float data_mem2[ATSC_DATA_SEGMENT_LENGTH];
@@ -59,6 +59,11 @@ namespace gr {
atsc_equalizer_impl();
~atsc_equalizer_impl();
+ void setup_rpc();
+
+ std::vector<float> taps() const;
+ std::vector<float> data() const;
+
virtual int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc
index 7a950e716e..b8ee91a52d 100644
--- a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.cc
@@ -56,9 +56,9 @@ namespace gr {
{
d_rs = init_rs_char(rs_init_symsize, rs_init_gfpoly, rs_init_fcr, rs_init_prim, rs_init_nroots);
assert (d_rs != 0);
- nerrors_corrrected_count = 0;
- bad_packet_count = 0;
- total_packets = 0;
+ d_nerrors_corrrected_count = 0;
+ d_bad_packet_count = 0;
+ d_total_packets = 0;
}
int atsc_rs_decoder_impl::decode (atsc_mpeg_packet_no_sync &out, const atsc_mpeg_packet_rs_encoded &in)
@@ -89,6 +89,24 @@ namespace gr {
}
int
+ atsc_rs_decoder_impl::num_errors_corrected() const
+ {
+ return d_nerrors_corrrected_count;
+ }
+
+ int
+ atsc_rs_decoder_impl::num_bad_packets() const
+ {
+ return d_bad_packet_count;
+ }
+
+ int
+ atsc_rs_decoder_impl::num_packets() const
+ {
+ return d_total_packets;
+ }
+
+ int
atsc_rs_decoder_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
@@ -102,24 +120,20 @@ namespace gr {
int nerrors_corrrected = decode(out[i], in[i]);
out[i].pli.set_transport_error(nerrors_corrrected == -1);
- if (nerrors_corrrected == -1)
- bad_packet_count++;
- else
- nerrors_corrrected_count += nerrors_corrrected;
+ if (nerrors_corrrected == -1) {
+ d_bad_packet_count++;
+ d_nerrors_corrrected_count += 10; // lower bound estimate; most this RS can fix
+ }
+ else {
+ d_nerrors_corrrected_count += nerrors_corrrected;
+ }
- total_packets++;
+ d_total_packets++;
#if 0
- if (total_packets > 1000) {
- // FIXME: convert to logger
- std::cout << "Error rate: "
- << (float)nerrors_corrrected_count/total_packets
- << "\tPacket error rate: "
- << (float)bad_packet_count/total_packets
- << std::endl;
-
- nerrors_corrrected_count = 0;
- bad_packet_count = 0;
- total_packets = 0;
+ if (d_total_packets > 1000) {
+ GR_LOG_INFO(d_logger, boost::format("Error rate: %1%\tPacket error rate: %2%") \
+ % ((float)d_nerrors_corrrected_count/(ATSC_MPEG_DATA_LENGTH*d_total_packets))
+ % ((float)d_bad_packet_count/d_total_packets));
}
#endif
}
@@ -127,5 +141,42 @@ namespace gr {
return noutput_items;
}
+
+ void
+ atsc_rs_decoder_impl::setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<atsc_rs_decoder, int >(
+ alias(), "num_errors_corrected",
+ &atsc_rs_decoder::num_errors_corrected,
+ pmt::from_long(0),
+ pmt::from_long(10000000),
+ pmt::from_long(0),
+ "", "Number of errors corrected", RPC_PRIVLVL_MIN,
+ DISPTIME)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<atsc_rs_decoder, int >(
+ alias(), "num_bad_packets",
+ &atsc_rs_decoder::num_bad_packets,
+ pmt::from_long(0),
+ pmt::from_long(10000000),
+ pmt::from_long(0),
+ "", "Number of bad packets", RPC_PRIVLVL_MIN,
+ DISPTIME)));
+
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<atsc_rs_decoder, int >(
+ alias(), "num_packets",
+ &atsc_rs_decoder::num_packets,
+ pmt::from_long(0),
+ pmt::from_long(10000000),
+ pmt::from_long(0),
+ "", "Number of packets", RPC_PRIVLVL_MIN,
+ DISPTIME)));
+#endif /* GR_CTRLPORT */
+ }
+
} /* namespace dtv */
} /* namespace gr */
diff --git a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h
index 57460128dc..adbc4879a9 100644
--- a/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h
+++ b/gr-dtv/lib/atsc/atsc_rs_decoder_impl.h
@@ -36,15 +36,22 @@ namespace gr {
class atsc_rs_decoder_impl : public atsc_rs_decoder
{
private:
- int nerrors_corrrected_count;
- int bad_packet_count;
- int total_packets;
+ int d_nerrors_corrrected_count;
+ int d_bad_packet_count;
+ int d_total_packets;
+ int d_total_bits;
void *d_rs;
public:
atsc_rs_decoder_impl();
~atsc_rs_decoder_impl();
+ void setup_rpc();
+
+ int num_errors_corrected() const;
+ int num_bad_packets() const;
+ int num_packets() const;
+
/*!
* Decode RS encoded packet.
* \returns a count of corrected symbols, or -1 if the block was uncorrectible.
diff --git a/gr-dtv/lib/atsc/atsc_single_viterbi.cc b/gr-dtv/lib/atsc/atsc_single_viterbi.cc
index 385940e453..011cc0fe96 100644
--- a/gr-dtv/lib/atsc/atsc_single_viterbi.cc
+++ b/gr-dtv/lib/atsc/atsc_single_viterbi.cc
@@ -28,7 +28,7 @@ namespace gr {
/* was_sent is a table of what symbol we get given what bit pair
was sent and what state we where in [state][pair] */
- const int atsc_single_viterbi::was_sent[4][4] = {
+ const int atsc_single_viterbi::d_was_sent[4][4] = {
{0,2,4,6},
{0,2,4,6},
{1,3,5,7},
@@ -37,7 +37,7 @@ namespace gr {
/* transition_table is a table of what state we were in
given current state and bit pair sent [state][pair] */
- const int atsc_single_viterbi::transition_table[4][4] = {
+ const int atsc_single_viterbi::d_transition_table[4][4] = {
{0,2,0,2},
{2,0,2,0},
{1,3,1,3},
@@ -49,11 +49,12 @@ namespace gr {
{
for (unsigned int i = 0; i<2; i++)
for (unsigned int j = 0; j<4; j++) {
- path_metrics[i][j] = 0;
- traceback[i][j] = 0;
+ d_path_metrics[i][j] = 0;
+ d_traceback[i][j] = 0;
}
- post_coder_state = 0;
- phase = 0;
+ d_post_coder_state = 0;
+ d_phase = 0;
+ d_best_state_metric = 100000;
}
atsc_single_viterbi::atsc_single_viterbi()
@@ -61,17 +62,24 @@ namespace gr {
reset();
}
+ float
+ atsc_single_viterbi::best_state_metric() const
+ {
+ return d_best_state_metric;
+ }
+
char
atsc_single_viterbi::decode(float input)
{
unsigned int best_state = 0;
- float best_state_metric = 100000;
+ //float best_state_metric = 100000;
+ d_best_state_metric = 100000;
/* Precompute distances from input to each possible symbol */
- float distances[8] = { (float)fabs( input + 7 ), (float)fabs( input + 5 ),
- (float)fabs( input + 3 ), (float)fabs( input + 1 ),
- (float)fabs( input - 1 ), (float)fabs( input - 3 ),
- (float)fabs( input - 5 ), (float)fabs( input - 7 ) };
+ float distances[8] = { fabsf( input + 7 ), fabsf( input + 5 ),
+ fabsf( input + 3 ), fabsf( input + 1 ),
+ fabsf( input - 1 ), fabsf( input - 3 ),
+ fabsf( input - 5 ), fabsf( input - 7 ) };
/* We start by iterating over all possible states */
for (unsigned int state = 0; state < 4; state++) {
@@ -79,15 +87,20 @@ namespace gr {
states to the state we are testing, we only need to look at
the 4 paths that can be taken given the 2-bit input */
int min_metric_symb = 0;
- float min_metric = distances[was_sent[state][0]] + path_metrics[phase][transition_table[state][0]];
+ float min_metric = distances[d_was_sent[state][0]] +
+ d_path_metrics[d_phase][d_transition_table[state][0]];
+
for (unsigned int symbol_sent = 1; symbol_sent < 4; symbol_sent++)
- if( (distances[was_sent[state][symbol_sent]] + path_metrics[phase][transition_table[state][symbol_sent]]) < min_metric) {
- min_metric = distances[was_sent[state][symbol_sent]] + path_metrics[phase][transition_table[state][symbol_sent]];
+ if( (distances[d_was_sent[state][symbol_sent]] +
+ d_path_metrics[d_phase][d_transition_table[state][symbol_sent]]) < min_metric) {
+ min_metric = distances[d_was_sent[state][symbol_sent]] +
+ d_path_metrics[d_phase][d_transition_table[state][symbol_sent]];
min_metric_symb = symbol_sent;
}
- path_metrics[phase^1][state] = min_metric;
- traceback[phase^1][state] = (((unsigned long long)min_metric_symb) << 62) | (traceback[phase][transition_table[state][min_metric_symb]] >> 2);
+ d_path_metrics[d_phase^1][state] = min_metric;
+ d_traceback[d_phase^1][state] = (((unsigned long long)min_metric_symb) << 62) |
+ (d_traceback[d_phase][d_transition_table[state][min_metric_symb]] >> 2);
/* If this is the most probable state so far remember it, this
only needs to be checked when we are about to output a path
@@ -98,26 +111,24 @@ namespace gr {
head state path will tend towards the optimal path with a
probability approaching 1 in just 8 or so transitions
*/
- if(min_metric <= best_state_metric) {
- best_state_metric = min_metric;
+ if(min_metric <= d_best_state_metric) {
+ d_best_state_metric = min_metric;
best_state = state;
}
}
- if(best_state_metric > 10000) {
+ if(d_best_state_metric > 10000) {
for(unsigned int state = 0; state < 4; state++)
- path_metrics[phase^1][state] -= best_state_metric;
+ d_path_metrics[d_phase^1][state] -= d_best_state_metric;
}
- phase ^= 1;
+ d_phase ^= 1;
- int y2 = (0x2 & traceback[phase][best_state]) >> 1;
- int x2 = y2 ^ post_coder_state;
- post_coder_state = y2;
+ int y2 = (0x2 & d_traceback[d_phase][best_state]) >> 1;
+ int x2 = y2 ^ d_post_coder_state;
+ d_post_coder_state = y2;
- return ( x2 << 1 ) | (0x1 & traceback[phase][best_state]);
+ return ( x2 << 1 ) | (0x1 & d_traceback[d_phase][best_state]);
}
} /* namespace dtv */
} /* namespace gr */
-
-
diff --git a/gr-dtv/lib/atsc/atsc_single_viterbi.h b/gr-dtv/lib/atsc/atsc_single_viterbi.h
index 3c756c7690..9522e2eb1b 100644
--- a/gr-dtv/lib/atsc/atsc_single_viterbi.h
+++ b/gr-dtv/lib/atsc/atsc_single_viterbi.h
@@ -44,14 +44,17 @@ namespace gr {
//! internal delay of decoder
static int delay () { return TB_LEN - 1; }
- protected:
- static const int transition_table[4][4];
- static const int was_sent[4][4];
+ float best_state_metric() const;
- float path_metrics [2][4];
- unsigned long long traceback [2][4];
- unsigned char phase;
- int post_coder_state;
+ protected:
+ static const int d_transition_table[4][4];
+ static const int d_was_sent[4][4];
+
+ float d_path_metrics [2][4];
+ unsigned long long d_traceback [2][4];
+ unsigned char d_phase;
+ int d_post_coder_state;
+ float d_best_state_metric;
};
} /* namespace dtv */
diff --git a/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc b/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc
index 430eb55a17..2284372dfb 100644
--- a/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc
+++ b/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.cc
@@ -77,6 +77,15 @@ namespace gr {
fifo[i]->reset();
}
+ std::vector<float>
+ atsc_viterbi_decoder_impl::decoder_metrics() const
+ {
+ std::vector<float> metrics(NCODERS);
+ for (int i = 0; i < NCODERS; i++)
+ metrics[i] = viterbi[i].best_state_metric();
+ return metrics;
+ }
+
int
atsc_viterbi_decoder_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
@@ -135,5 +144,21 @@ namespace gr {
return noutput_items;
}
+ void
+ atsc_viterbi_decoder_impl::setup_rpc()
+ {
+#ifdef GR_CTRLPORT
+ add_rpc_variable(
+ rpcbasic_sptr(new rpcbasic_register_get<atsc_viterbi_decoder, std::vector<float> >(
+ alias(), "decoder_metrics",
+ &atsc_viterbi_decoder::decoder_metrics,
+ pmt::make_f32vector(1,0),
+ pmt::make_f32vector(1,100000),
+ pmt::make_f32vector(1,0),
+ "", "Viterbi decoder metrics", RPC_PRIVLVL_MIN,
+ DISPTIME)));
+#endif /* GR_CTRLPORT */
+ }
+
} /* namespace dtv */
} /* namespace gr */
diff --git a/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.h b/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.h
index b4fbbd1033..ef4faab313 100644
--- a/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.h
+++ b/gr-dtv/lib/atsc/atsc_viterbi_decoder_impl.h
@@ -63,8 +63,12 @@ namespace gr {
atsc_viterbi_decoder_impl();
~atsc_viterbi_decoder_impl();
+ void setup_rpc();
+
void reset();
+ std::vector<float> decoder_metrics() const;
+
virtual int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
diff --git a/gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.cc b/gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.cc
new file mode 100644
index 0000000000..87c706b445
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.cc
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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 "catv_frame_sync_enc_bb_impl.h"
+
+namespace gr {
+ namespace dtv {
+
+ catv_frame_sync_enc_bb::sptr
+ catv_frame_sync_enc_bb::make(int ctrlword)
+ {
+ return gnuradio::get_initial_sptr
+ (new catv_frame_sync_enc_bb_impl(ctrlword));
+ }
+
+ /*
+ * The private constructor
+ */
+ catv_frame_sync_enc_bb_impl::catv_frame_sync_enc_bb_impl(int ctrlword)
+ : gr::block("catv_frame_sync_enc_bb",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(unsigned char)))
+ {
+ set_output_multiple(60 * 128 + 6);
+ control_word = ctrlword;
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ catv_frame_sync_enc_bb_impl::~catv_frame_sync_enc_bb_impl()
+ {
+ }
+
+ void
+ catv_frame_sync_enc_bb_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items / (60 * 128 + 6) * (60 * 128);
+ }
+
+ int
+ catv_frame_sync_enc_bb_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 i = 0, j = 0;
+ while (i < noutput_items) {
+ memcpy(out + i, in + j, 60 * 128);
+ i += 60 * 128;
+ j += 60 * 128;
+
+ out[i++] = 0x75;
+ out[i++] = 0x2C;
+ out[i++] = 0x0D;
+ out[i++] = 0x6C;
+ out[i++] = control_word << 3;
+ out[i++] = 0x00;
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (j);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.h b/gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.h
new file mode 100644
index 0000000000..fb924f7a14
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_frame_sync_enc_bb_impl.h
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_FRAME_SYNC_ENC_BB_IMPL_H
+#define INCLUDED_DTV_CATV_FRAME_SYNC_ENC_BB_IMPL_H
+
+#include <gnuradio/dtv/catv_frame_sync_enc_bb.h>
+
+namespace gr {
+ namespace dtv {
+
+ class catv_frame_sync_enc_bb_impl : public catv_frame_sync_enc_bb
+ {
+ private:
+ int control_word;
+
+ public:
+ catv_frame_sync_enc_bb_impl(int ctrlword);
+ ~catv_frame_sync_enc_bb_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_CATV_FRAME_SYNC_ENC_BB_IMPL_H */
+
diff --git a/gr-dtv/lib/catv/catv_randomizer_bb_impl.cc b/gr-dtv/lib/catv/catv_randomizer_bb_impl.cc
new file mode 100644
index 0000000000..698288dcd3
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_randomizer_bb_impl.cc
@@ -0,0 +1,104 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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 "catv_randomizer_bb_impl.h"
+
+namespace gr {
+ namespace dtv {
+
+ catv_randomizer_bb::sptr
+ catv_randomizer_bb::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new catv_randomizer_bb_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ catv_randomizer_bb_impl::catv_randomizer_bb_impl()
+ : gr::sync_block("catv_randomizer_bb",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(unsigned char)))
+ {
+ init_rand();
+
+ offset = 0;
+ max_offset = 60 * 128;
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ catv_randomizer_bb_impl::~catv_randomizer_bb_impl()
+ {
+ }
+
+ void
+ catv_randomizer_bb_impl::init_rand()
+ {
+ unsigned char c2 = 0x7F, c1 = 0x7F, c0 = 0x7F;
+ unsigned char c2_new, c1_new, c0_new;
+ int n, i;
+
+ for (n = 0; n < 60 * 128; n++) {
+ rseq[n] = c2;
+ c2_new = c1;
+ c1_new = c0 ^ c2;
+ c0_new = c2;
+ for (i = 0; i < 3; i++) {
+ c0_new <<= 1;
+ if (c0_new & 0x80) {
+ c0_new = (c0_new & 0x7F) ^ 0x09;
+ }
+ }
+ c2 = c2_new;
+ c1 = c1_new;
+ c0 = c0_new;
+ }
+ }
+
+ int
+ catv_randomizer_bb_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; i++) {
+ out[i] = in[i] ^ rseq[offset++];
+ if (offset == max_offset) {
+ offset = 0;
+ }
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/catv/catv_randomizer_bb_impl.h b/gr-dtv/lib/catv/catv_randomizer_bb_impl.h
new file mode 100644
index 0000000000..e4e40f8f6e
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_randomizer_bb_impl.h
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_RANDOMIZER_BB_IMPL_H
+#define INCLUDED_DTV_CATV_RANDOMIZER_BB_IMPL_H
+
+#include <gnuradio/dtv/catv_randomizer_bb.h>
+
+namespace gr {
+ namespace dtv {
+
+ class catv_randomizer_bb_impl : public catv_randomizer_bb
+ {
+ private:
+ unsigned char rseq[60 * 128];
+ int offset, max_offset;
+ void init_rand();
+
+ public:
+ catv_randomizer_bb_impl();
+ ~catv_randomizer_bb_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_CATV_RANDOMIZER_BB_IMPL_H */
+
diff --git a/gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.cc b/gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.cc
new file mode 100644
index 0000000000..06a1f12c3e
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.cc
@@ -0,0 +1,153 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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 "catv_reed_solomon_enc_bb_impl.h"
+
+namespace gr {
+ namespace dtv {
+
+ catv_reed_solomon_enc_bb::sptr
+ catv_reed_solomon_enc_bb::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new catv_reed_solomon_enc_bb_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ catv_reed_solomon_enc_bb_impl::catv_reed_solomon_enc_bb_impl()
+ : gr::block("catv_reed_solomon_enc_bb",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(unsigned char)))
+ {
+ set_output_multiple(128);
+ init_rs();
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ catv_reed_solomon_enc_bb_impl::~catv_reed_solomon_enc_bb_impl()
+ {
+ }
+
+ void
+ catv_reed_solomon_enc_bb_impl::init_rs()
+ {
+ unsigned char x;
+ int i, j;
+
+ gf_exp[0] = 1;
+ gf_log[1] = 0;
+
+ x = 1;
+ for (i = 1; i < 127; i++) {
+ x <<= 1;
+ if (x & 0x80) {
+ x = (x & 0x7F) ^ 0x09;
+ }
+ gf_exp[i] = x;
+ gf_log[x] = i;
+ }
+ for (; i < 256; i++) {
+ gf_exp[i] = gf_exp[i - 127];
+ }
+
+ for (i = 0; i < 128; i++) {
+ for (j = 0; j < 128; j++) {
+ if ((i == 0) || (j == 0)) {
+ gf_mul_table[i][j] = 0;
+ } else {
+ gf_mul_table[i][j] = gf_exp[gf_log[i] + gf_log[j]];
+ }
+ }
+ }
+ }
+
+ unsigned char
+ catv_reed_solomon_enc_bb_impl::gf_poly_eval(unsigned char *p, int len, unsigned char x)
+ {
+ unsigned char y = p[0];
+ int i;
+
+ for (i = 1; i < len; i++) {
+ y = gf_mul_table[y][x] ^ p[i];
+ }
+ return y;
+ }
+
+ void
+ catv_reed_solomon_enc_bb_impl::reed_solomon_enc(const unsigned char *message, unsigned char *output)
+ {
+ // Generator polynomial from p.7 of ANSI/SCTE 07 2013
+ unsigned char g[] = {1, gf_exp[52], gf_exp[116], gf_exp[119], gf_exp[61], gf_exp[15]};
+ int i, j;
+
+ memcpy(output, message, 122);
+ memset(output + 122, 0, 6);
+
+ for (i = 0; i < 122; i++) {
+ for (j = 1; j < 6; j++) {
+ output[i + j] ^= gf_mul_table[output[i]][g[j]];
+ }
+ output[i] = message[i];
+ }
+
+ output[127] = gf_poly_eval(output, 128, gf_exp[6]);
+ }
+
+ void
+ catv_reed_solomon_enc_bb_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = (noutput_items / 128) * 122;
+ }
+
+ int
+ catv_reed_solomon_enc_bb_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 j = 0;
+
+ for (int i = 0; i < noutput_items; i += 128) {
+ reed_solomon_enc(in + j, out + i);
+ j += 122;
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (j);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.h b/gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.h
new file mode 100644
index 0000000000..84e4cb500e
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_reed_solomon_enc_bb_impl.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_REED_SOLOMON_ENC_BB_IMPL_H
+#define INCLUDED_DTV_CATV_REED_SOLOMON_ENC_BB_IMPL_H
+
+#include <gnuradio/dtv/catv_reed_solomon_enc_bb.h>
+
+namespace gr {
+ namespace dtv {
+
+ class catv_reed_solomon_enc_bb_impl : public catv_reed_solomon_enc_bb
+ {
+ private:
+ unsigned char gf_mul_table[128][128];
+ unsigned char gf_exp[256];
+ unsigned char gf_log[128];
+
+ void init_rs();
+ unsigned char gf_poly_eval(unsigned char *p, int len, unsigned char x);
+ void reed_solomon_enc(const unsigned char *message, unsigned char *output);
+
+ public:
+ catv_reed_solomon_enc_bb_impl();
+ ~catv_reed_solomon_enc_bb_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_CATV_REED_SOLOMON_ENC_BB_IMPL_H */
+
diff --git a/gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.cc b/gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.cc
new file mode 100644
index 0000000000..4082e8265c
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.cc
@@ -0,0 +1,131 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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 "catv_transport_framing_enc_bb_impl.h"
+
+namespace gr {
+ namespace dtv {
+
+ catv_transport_framing_enc_bb::sptr
+ catv_transport_framing_enc_bb::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new catv_transport_framing_enc_bb_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ catv_transport_framing_enc_bb_impl::catv_transport_framing_enc_bb_impl()
+ : gr::sync_block("catv_transport_framing_enc_bb",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(unsigned char)))
+ {
+ set_output_multiple(188);
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ catv_transport_framing_enc_bb_impl::~catv_transport_framing_enc_bb_impl()
+ {
+ }
+
+ unsigned char catv_transport_framing_enc_bb_impl::compute_sum(const unsigned char *bytes)
+ {
+ unsigned char i, bit, out, out1, out2, out3;
+
+ unsigned char tapsG = 0xB1; // 10110001
+ unsigned char tapsB = 0x45; // 1000101
+
+ unsigned char register1 = 0;
+ unsigned char register2 = 0;
+ unsigned char register3 = 0;
+
+ unsigned char result = 0x67;
+
+ unsigned char first7[] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+ for (i = 0; i < 8; i++) {
+ bit = (bytes[0] >> (7-i)) & 1;
+ out = (register1 & 1) ^ bit;
+ if (i < 7) {
+ first7[i+1] = out;
+ }
+ register1 >>= 1;
+ if (out == 1) {
+ register1 ^= tapsG;
+ }
+ }
+
+ for (i = 1; i < 187; i++) {
+ register1 = crctable[((register1) ^ BitReverseTable[bytes[i]]) & 0xff];
+ }
+
+ for (i = 0; i < 8; i++) {
+ out1 = register1 & 1;
+ register1 >>= 1;
+ if (out1 == 1) {
+ register1 ^= tapsG;
+ }
+
+ out2 = (register2 & 1) ^ first7[i];
+ register2 >>= 1;
+ if (first7[i] == 1) {
+ register2 ^= tapsB;
+ }
+
+ out3 = (register3 & 1) ^ out1 ^ out2;
+ register3 >>= 1;
+ if ((out1 ^ out2) == 1) {
+ register3 ^= tapsG;
+ }
+
+ result ^= (out3 << (7-i));
+ }
+
+ return result;
+ }
+
+ int
+ catv_transport_framing_enc_bb_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; i += 188) {
+ memcpy(out + i, in + i + 1, 187);
+ out[i + 187] = compute_sum(in + i + 1);
+ }
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.h b/gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.h
new file mode 100644
index 0000000000..fe69bc01f6
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_transport_framing_enc_bb_impl.h
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_TRANSPORT_FRAMING_ENC_BB_IMPL_H
+#define INCLUDED_DTV_CATV_TRANSPORT_FRAMING_ENC_BB_IMPL_H
+
+#include <gnuradio/dtv/catv_transport_framing_enc_bb.h>
+
+namespace gr {
+ namespace dtv {
+ static const unsigned char crctable[] = {
+ 0x00,0x1b,0x36,0x2d,0x6c,0x77,0x5a,0x41,0xd8,0xc3,0xee,0xf5,0xb4,0xaf,0x82,0x99,
+ 0xd3,0xc8,0xe5,0xfe,0xbf,0xa4,0x89,0x92,0x0b,0x10,0x3d,0x26,0x67,0x7c,0x51,0x4a,
+ 0xc5,0xde,0xf3,0xe8,0xa9,0xb2,0x9f,0x84,0x1d,0x06,0x2b,0x30,0x71,0x6a,0x47,0x5c,
+ 0x16,0x0d,0x20,0x3b,0x7a,0x61,0x4c,0x57,0xce,0xd5,0xf8,0xe3,0xa2,0xb9,0x94,0x8f,
+ 0xe9,0xf2,0xdf,0xc4,0x85,0x9e,0xb3,0xa8,0x31,0x2a,0x07,0x1c,0x5d,0x46,0x6b,0x70,
+ 0x3a,0x21,0x0c,0x17,0x56,0x4d,0x60,0x7b,0xe2,0xf9,0xd4,0xcf,0x8e,0x95,0xb8,0xa3,
+ 0x2c,0x37,0x1a,0x01,0x40,0x5b,0x76,0x6d,0xf4,0xef,0xc2,0xd9,0x98,0x83,0xae,0xb5,
+ 0xff,0xe4,0xc9,0xd2,0x93,0x88,0xa5,0xbe,0x27,0x3c,0x11,0x0a,0x4b,0x50,0x7d,0x66,
+ 0xb1,0xaa,0x87,0x9c,0xdd,0xc6,0xeb,0xf0,0x69,0x72,0x5f,0x44,0x05,0x1e,0x33,0x28,
+ 0x62,0x79,0x54,0x4f,0x0e,0x15,0x38,0x23,0xba,0xa1,0x8c,0x97,0xd6,0xcd,0xe0,0xfb,
+ 0x74,0x6f,0x42,0x59,0x18,0x03,0x2e,0x35,0xac,0xb7,0x9a,0x81,0xc0,0xdb,0xf6,0xed,
+ 0xa7,0xbc,0x91,0x8a,0xcb,0xd0,0xfd,0xe6,0x7f,0x64,0x49,0x52,0x13,0x08,0x25,0x3e,
+ 0x58,0x43,0x6e,0x75,0x34,0x2f,0x02,0x19,0x80,0x9b,0xb6,0xad,0xec,0xf7,0xda,0xc1,
+ 0x8b,0x90,0xbd,0xa6,0xe7,0xfc,0xd1,0xca,0x53,0x48,0x65,0x7e,0x3f,0x24,0x09,0x12,
+ 0x9d,0x86,0xab,0xb0,0xf1,0xea,0xc7,0xdc,0x45,0x5e,0x73,0x68,0x29,0x32,0x1f,0x04,
+ 0x4e,0x55,0x78,0x63,0x22,0x39,0x14,0x0f,0x96,0x8d,0xa0,0xbb,0xfa,0xe1,0xcc,0xd7
+ };
+
+ static const unsigned char BitReverseTable[] = {
+ 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+ 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+ 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+ 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+ 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+ 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+ 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+ 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+ 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+ 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+ 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+ 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+ 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+ 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+ 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+ 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+ };
+
+ class catv_transport_framing_enc_bb_impl : public catv_transport_framing_enc_bb
+ {
+ private:
+ unsigned char compute_sum(const unsigned char *bytes);
+
+ public:
+ catv_transport_framing_enc_bb_impl();
+ ~catv_transport_framing_enc_bb_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_CATV_TRANSPORT_FRAMING_ENC_BB_IMPL_H */
+
diff --git a/gr-dtv/lib/catv/catv_trellis_enc_bb_impl.cc b/gr-dtv/lib/catv/catv_trellis_enc_bb_impl.cc
new file mode 100644
index 0000000000..8fdb8722b6
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_trellis_enc_bb_impl.cc
@@ -0,0 +1,193 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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 "catv_trellis_enc_bb_impl.h"
+
+namespace gr {
+ namespace dtv {
+
+ catv_trellis_enc_bb::sptr
+ catv_trellis_enc_bb::make()
+ {
+ return gnuradio::get_initial_sptr
+ (new catv_trellis_enc_bb_impl());
+ }
+
+ /*
+ * The private constructor
+ */
+ catv_trellis_enc_bb_impl::catv_trellis_enc_bb_impl()
+ : gr::block("catv_trellis_enc_bb",
+ gr::io_signature::make(1, 1, sizeof(unsigned char)),
+ gr::io_signature::make(1, 1, sizeof(unsigned char)))
+ {
+ set_output_multiple(5);
+
+ init_trellis();
+
+ Xq = 0;
+ Yq = 0;
+ XYp = 0;
+ }
+
+ /*
+ * Our virtual destructor.
+ */
+ catv_trellis_enc_bb_impl::~catv_trellis_enc_bb_impl()
+ {
+ }
+
+ void
+ catv_trellis_enc_bb_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
+ {
+ ninput_items_required[0] = noutput_items / 5 * 4;
+ }
+
+ void
+ catv_trellis_enc_bb_impl::diff_precoder(unsigned char W, unsigned char Z, unsigned char *Xp, unsigned char *Yp)
+ {
+ unsigned char common, newX, newY;
+
+ common = (Z & (*Xp ^ *Yp));
+ newX = W ^ *Xp ^ common;
+ newY = Z ^ W ^ *Yp ^ common;
+
+ *Xp = newX;
+ *Yp = newY;
+ }
+
+ void
+ catv_trellis_enc_bb_impl::init_trellis()
+ {
+ unsigned char XYp, W, Z, X, Y, Xp, Yp, state, xy, Xq;
+ int i, n;
+
+ for (XYp = 0; XYp < 4; XYp++) {
+ for (W = 0; W < 16; W++) {
+ for (Z = 0; Z < 16; Z++) {
+ X = 0;
+ Y = 0;
+ Xp = (XYp & 0b10) >> 1;
+ Yp = (XYp & 0b01);
+ for (i = 0; i < 4; i++) {
+ diff_precoder((W >> i) & 1, (Z >> i) & 1, &Xp, &Yp);
+ X |= (Xp << i);
+ Y |= (Yp << i);
+ }
+ diff_precoder_table[XYp][W][Z][0] = (Xp << 1) + Yp;
+ diff_precoder_table[XYp][W][Z][1] = X;
+ diff_precoder_table[XYp][W][Z][2] = Y;
+ }
+ }
+ }
+
+ for (i = 0; i < 32; i++) {
+ G1table[i] = (i >> 4) ^ ((i & 0x04) >> 2) ^ (i & 1);
+ G2table[i] = (i >> 4) ^ ((i & 0x08) >> 3) ^ ((i & 0x04) >> 2) ^ ((i & 0x02) >> 1) ^ (i & 1);
+ }
+
+ memset(trellis_table_x, 0, 16*16*6);
+ memset(trellis_table_y, 0, 16*16*6);
+ for (state = 0; state < 16; state++) {
+ for (xy = 0; xy < 16; xy++) {
+ i = 0;
+ Xq = state;
+ for (n = 0; n < 4; n++) {
+ Xq = (Xq << 1) + ((xy >> n) & 1);
+
+ if (n == 3) {
+ trellis_table_x[state][xy][i+1] |= G1table[Xq] << 3;
+ trellis_table_y[state][xy][i+1] |= G1table[Xq];
+ i += 1;
+ }
+ trellis_table_x[state][xy][i+1] |= G2table[Xq] << 3;
+ trellis_table_y[state][xy][i+1] |= G2table[Xq];
+ i += 1;
+
+ Xq &= 0x0F;
+ }
+
+ trellis_table_x[state][xy][0] = Xq;
+ trellis_table_y[state][xy][0] = Xq;
+ }
+ }
+ }
+
+ void
+ catv_trellis_enc_bb_impl::trellis_code(const unsigned char *rs, unsigned char *qs)
+ {
+ unsigned char X, Y;
+ int A, B, n;
+
+ A = (rs[1] << 7) | rs[0];
+ B = (rs[3] << 7) | rs[2];
+
+ memset(qs, 0, 5);
+
+ for (n = 0; n < 5; n++) {
+ qs[n] |= ((A >> (2*n)) & 3) << 4;
+ qs[n] |= ((B >> (2*n)) & 3) << 1;
+ }
+
+ X = diff_precoder_table[XYp][A >> 10][B >> 10][1];
+ Y = diff_precoder_table[XYp][A >> 10][B >> 10][2];
+ XYp = diff_precoder_table[XYp][A >> 10][B >> 10][0];
+
+ for (n = 0; n < 5; n++) {
+ qs[n] |= trellis_table_x[Xq][X][1+n];
+ qs[n] |= trellis_table_y[Yq][Y][1+n];
+ }
+ Xq = trellis_table_x[Xq][X][0];
+ Yq = trellis_table_y[Yq][Y][0];
+ }
+
+ int
+ catv_trellis_enc_bb_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 i = 0, j = 0;
+
+ while (i < noutput_items) {
+ trellis_code(in + j, out + i);
+ i += 5;
+ j += 4;
+ }
+
+ // Tell runtime system how many input items we consumed on
+ // each input stream.
+ consume_each (j);
+
+ // Tell runtime system how many output items we produced.
+ return noutput_items;
+ }
+
+ } /* namespace dtv */
+} /* namespace gr */
+
diff --git a/gr-dtv/lib/catv/catv_trellis_enc_bb_impl.h b/gr-dtv/lib/catv/catv_trellis_enc_bb_impl.h
new file mode 100644
index 0000000000..aa7874d929
--- /dev/null
+++ b/gr-dtv/lib/catv/catv_trellis_enc_bb_impl.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2016 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_CATV_TRELLIS_ENC_BB_IMPL_H
+#define INCLUDED_DTV_CATV_TRELLIS_ENC_BB_IMPL_H
+
+#include <gnuradio/dtv/catv_trellis_enc_bb.h>
+
+namespace gr {
+ namespace dtv {
+
+ class catv_trellis_enc_bb_impl : public catv_trellis_enc_bb
+ {
+ private:
+ unsigned char diff_precoder_table[4][16][16][3];
+ unsigned char G1table[32];
+ unsigned char G2table[32];
+ unsigned char trellis_table_x[16][16][6];
+ unsigned char trellis_table_y[16][16][6];
+ unsigned char Xq, Yq, XYp;
+
+ void diff_precoder(unsigned char W, unsigned char Z, unsigned char *Xp, unsigned char *Yp);
+ void init_trellis();
+ void trellis_code(const unsigned char *rs, unsigned char *qs);
+
+ public:
+ catv_trellis_enc_bb_impl();
+ ~catv_trellis_enc_bb_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);
+ };
+
+ } // namespace dtv
+} // namespace gr
+
+#endif /* INCLUDED_DTV_CATV_TRELLIS_ENC_BB_IMPL_H */
+
diff --git a/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.cc b/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.cc
index c8579d1c1e..d1f3b4aa27 100644
--- a/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.cc
+++ b/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2015 Free Software Foundation, Inc.
+ * Copyright 2015,2016 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
@@ -29,16 +29,16 @@ namespace gr {
namespace dtv {
dvbs2_modulator_bc::sptr
- dvbs2_modulator_bc::make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation)
+ dvbs2_modulator_bc::make(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbs2_interpolation_t interpolation)
{
return gnuradio::get_initial_sptr
- (new dvbs2_modulator_bc_impl(framesize, rate, constellation));
+ (new dvbs2_modulator_bc_impl(framesize, rate, constellation, interpolation));
}
/*
* The private constructor
*/
- dvbs2_modulator_bc_impl::dvbs2_modulator_bc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation)
+ dvbs2_modulator_bc_impl::dvbs2_modulator_bc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbs2_interpolation_t interpolation)
: gr::block("dvbs2_modulator_bc",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(1, 1, sizeof(gr_complex)))
@@ -1660,6 +1660,72 @@ namespace gr {
m_256apsk[255] = gr_complex((r6 * cos(43 * M_PI / 32.0)), (r6 * sin(43 * M_PI / 32.0)));
}
break;
+ case MOD_64QAM:
+ m_64apsk[0] = gr_complex( 1.0, 1.0);
+ m_64apsk[1] = gr_complex( 1.0, -1.0);
+ m_64apsk[2] = gr_complex( 1.0, -3.0);
+ m_64apsk[3] = gr_complex( -3.0, -1.0);
+ m_64apsk[4] = gr_complex( -3.0, 1.0);
+ m_64apsk[5] = gr_complex( 1.0, 3.0);
+ m_64apsk[6] = gr_complex( -3.0, -3.0);
+ m_64apsk[7] = gr_complex( -3.0, 3.0);
+ m_64apsk[8] = gr_complex( -1.0, 1.0);
+ m_64apsk[9] = gr_complex( -1.0, -1.0);
+ m_64apsk[10] = gr_complex( 3.0, 1.0);
+ m_64apsk[11] = gr_complex(-1.0, 3.0);
+ m_64apsk[12] = gr_complex(-1.0, -3.0);
+ m_64apsk[13] = gr_complex( 3.0, -1.0);
+ m_64apsk[14] = gr_complex( 3.0, -3.0);
+ m_64apsk[15] = gr_complex( 3.0, 3.0);
+ m_64apsk[16] = gr_complex( 5.0, 1.0);
+ m_64apsk[17] = gr_complex( 1.0, -5.0);
+ m_64apsk[18] = gr_complex( 1.0, -7.0);
+ m_64apsk[19] = gr_complex(-7.0, -1.0);
+ m_64apsk[20] = gr_complex(-3.0, 5.0);
+ m_64apsk[21] = gr_complex( 5.0, 3.0);
+ m_64apsk[22] = gr_complex(-7.0, -3.0);
+ m_64apsk[23] = gr_complex(-3.0, 7.0);
+ m_64apsk[24] = gr_complex(-1.0, 5.0);
+ m_64apsk[25] = gr_complex(-5.0, -1.0);
+ m_64apsk[26] = gr_complex( 7.0, 1.0);
+ m_64apsk[27] = gr_complex(-1.0, 7.0);
+ m_64apsk[28] = gr_complex(-5.0, -3.0);
+ m_64apsk[29] = gr_complex( 3.0, -5.0);
+ m_64apsk[30] = gr_complex( 3.0, -7.0);
+ m_64apsk[31] = gr_complex( 7.0, 3.0);
+ m_64apsk[32] = gr_complex( 1.0, 5.0);
+ m_64apsk[33] = gr_complex( 5.0, -1.0);
+ m_64apsk[34] = gr_complex( 5.0, -3.0);
+ m_64apsk[35] = gr_complex(-3.0, -5.0);
+ m_64apsk[36] = gr_complex(-7.0, 1.0);
+ m_64apsk[37] = gr_complex( 1.0, 7.0);
+ m_64apsk[38] = gr_complex(-3.0, -7.0);
+ m_64apsk[39] = gr_complex(-7.0, 3.0);
+ m_64apsk[40] = gr_complex(-5.0, 1.0);
+ m_64apsk[41] = gr_complex(-1.0, -5.0);
+ m_64apsk[42] = gr_complex( 3.0, 5.0);
+ m_64apsk[43] = gr_complex(-5.0, 3.0);
+ m_64apsk[44] = gr_complex(-1.0, -7.0);
+ m_64apsk[45] = gr_complex( 7.0, -1.0);
+ m_64apsk[46] = gr_complex( 7.0, -3.0);
+ m_64apsk[47] = gr_complex( 3.0, 7.0);
+ m_64apsk[48] = gr_complex( 5.0, 5.0);
+ m_64apsk[49] = gr_complex( 5.0, -5.0);
+ m_64apsk[50] = gr_complex( 5.0, -7.0);
+ m_64apsk[51] = gr_complex(-7.0, -5.0);
+ m_64apsk[52] = gr_complex(-7.0, 5.0);
+ m_64apsk[53] = gr_complex( 5.0, 7.0);
+ m_64apsk[54] = gr_complex(-7.0, -7.0);
+ m_64apsk[55] = gr_complex(-7.0, 7.0);
+ m_64apsk[56] = gr_complex(-5.0, 5.0);
+ m_64apsk[57] = gr_complex(-5.0, -5.0);
+ m_64apsk[58] = gr_complex( 7.0, 5.0);
+ m_64apsk[59] = gr_complex(-5.0, 7.0);
+ m_64apsk[60] = gr_complex(-5.0, -7.0);
+ m_64apsk[61] = gr_complex( 7.0, -5.0);
+ m_64apsk[62] = gr_complex( 7.0, -7.0);
+ m_64apsk[63] = gr_complex( 7.0, 7.0);
+ break;
default:
m_qpsk[0] = gr_complex((r1 * cos(M_PI / 4.0)), (r1 * sin(M_PI / 4.0)));
m_qpsk[1] = gr_complex((r1 * cos(7 * M_PI / 4.0)), (r1 * sin(7 * M_PI / 4.0)));
@@ -1668,6 +1734,7 @@ namespace gr {
break;
}
signal_constellation = constellation;
+ signal_interpolation = interpolation;
set_output_multiple(2);
}
@@ -1681,7 +1748,12 @@ namespace gr {
void
dvbs2_modulator_bc_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
- ninput_items_required[0] = noutput_items;
+ if (signal_interpolation == INTERPOLATION_OFF) {
+ ninput_items_required[0] = noutput_items;
+ }
+ else {
+ ninput_items_required[0] = noutput_items / 2;
+ }
}
int
@@ -1693,67 +1765,145 @@ namespace gr {
const unsigned char *in = (const unsigned char *) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];
int index;
+ gr_complex zero;
- switch (signal_constellation) {
- case MOD_QPSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_qpsk[index & 0x3];
- }
- break;
- case MOD_8PSK:
- case MOD_8APSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_8psk[index & 0x7];
- }
- break;
- case MOD_16APSK:
- case MOD_8_8APSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_16apsk[index & 0xf];
- }
- break;
- case MOD_32APSK:
- case MOD_4_12_16APSK:
- case MOD_4_8_4_16APSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_32apsk[index & 0x1f];
- }
- break;
- case MOD_64APSK:
- case MOD_8_16_20_20APSK:
- case MOD_4_12_20_28APSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_64apsk[index & 0x3f];
- }
- break;
- case MOD_128APSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_128apsk[index & 0x7f];
- }
- break;
- case MOD_256APSK:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_256apsk[index & 0xff];
- }
- break;
- default:
- for (int i = 0; i < noutput_items; i++) {
- index = *in++;
- *out++ = m_qpsk[index & 0x3];
- }
- break;
+ zero = gr_complex(0.0, 0.0);
+
+ if (signal_interpolation == INTERPOLATION_OFF) {
+ switch (signal_constellation) {
+ case MOD_QPSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_qpsk[index & 0x3];
+ }
+ break;
+ case MOD_8PSK:
+ case MOD_8APSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_8psk[index & 0x7];
+ }
+ break;
+ case MOD_16APSK:
+ case MOD_8_8APSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_16apsk[index & 0xf];
+ }
+ break;
+ case MOD_32APSK:
+ case MOD_4_12_16APSK:
+ case MOD_4_8_4_16APSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_32apsk[index & 0x1f];
+ }
+ break;
+ case MOD_64APSK:
+ case MOD_64QAM:
+ case MOD_8_16_20_20APSK:
+ case MOD_4_12_20_28APSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_64apsk[index & 0x3f];
+ }
+ break;
+ case MOD_128APSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_128apsk[index & 0x7f];
+ }
+ break;
+ case MOD_256APSK:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_256apsk[index & 0xff];
+ }
+ break;
+ default:
+ for (int i = 0; i < noutput_items; i++) {
+ index = *in++;
+ *out++ = m_qpsk[index & 0x3];
+ }
+ break;
+ }
+ }
+ else {
+ switch (signal_constellation) {
+ case MOD_QPSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_qpsk[index & 0x3];
+ *out++ = zero;
+ }
+ break;
+ case MOD_8PSK:
+ case MOD_8APSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_8psk[index & 0x7];
+ *out++ = zero;
+ }
+ break;
+ case MOD_16APSK:
+ case MOD_8_8APSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_16apsk[index & 0xf];
+ *out++ = zero;
+ }
+ break;
+ case MOD_32APSK:
+ case MOD_4_12_16APSK:
+ case MOD_4_8_4_16APSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_32apsk[index & 0x1f];
+ *out++ = zero;
+ }
+ break;
+ case MOD_64APSK:
+ case MOD_64QAM:
+ case MOD_8_16_20_20APSK:
+ case MOD_4_12_20_28APSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_64apsk[index & 0x3f];
+ *out++ = zero;
+ }
+ break;
+ case MOD_128APSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_128apsk[index & 0x7f];
+ *out++ = zero;
+ }
+ break;
+ case MOD_256APSK:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_256apsk[index & 0xff];
+ *out++ = zero;
+ }
+ break;
+ default:
+ for (int i = 0; i < noutput_items / 2; i++) {
+ index = *in++;
+ *out++ = m_qpsk[index & 0x3];
+ *out++ = zero;
+ }
+ break;
+ }
}
// Tell runtime system how many input items we consumed on
// each input stream.
- consume_each (noutput_items);
+ if (signal_interpolation == INTERPOLATION_OFF) {
+ consume_each (noutput_items);
+ }
+ else {
+ consume_each (noutput_items / 2);
+ }
// Tell runtime system how many output items we produced.
return noutput_items;
diff --git a/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.h b/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.h
index 8507878b0e..4fdbb149df 100644
--- a/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.h
+++ b/gr-dtv/lib/dvbs2/dvbs2_modulator_bc_impl.h
@@ -31,6 +31,7 @@ namespace gr {
{
private:
int signal_constellation;
+ int signal_interpolation;
gr_complex m_qpsk[4];
gr_complex m_8psk[8];
gr_complex m_16apsk[16];
@@ -40,7 +41,7 @@ namespace gr {
gr_complex m_256apsk[256];
public:
- dvbs2_modulator_bc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation);
+ dvbs2_modulator_bc_impl(dvb_framesize_t framesize, dvb_code_rate_t rate, dvb_constellation_t constellation, dvbs2_interpolation_t interpolation);
~dvbs2_modulator_bc_impl();
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc
index 84b20f9ad4..abef1d0510 100644
--- a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc
+++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.cc
@@ -34,12 +34,12 @@ namespace gr {
namespace dtv {
int
- dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha)
+ dvbt_ofdm_sym_acquisition_impl::peak_detect_init(float threshold_factor_rise, float alpha)
{
d_avg_alpha = alpha;
d_threshold_factor_rise = threshold_factor_rise;
- d_threshold_factor_fall = threshold_factor_fall;
- d_avg = 0;
+ d_avg_max = - (float)INFINITY;
+ d_avg_min = (float)INFINITY;
return (0);
}
@@ -47,56 +47,50 @@ namespace gr {
int
dvbt_ofdm_sym_acquisition_impl::peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max)
{
- int state = 0;
- float peak_val = -(float)INFINITY; int peak_index = 0; int peak_pos_length = 0;
+ unsigned int peak_index = 0;
+ int peak_pos_length = 0;
- int i = 0;
+ volk_32f_index_max_16u(&peak_index, &datain[0], datain_length);
- while(i < datain_length) {
- if (state == 0) {
- if (datain[i] > d_avg * d_threshold_factor_rise) {
- state = 1;
- }
- else {
- d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg;
- i++;
- }
+ peak_pos_length = 1;
+ if (datain_length >= d_fft_length) {
+ float min = datain[(peak_index + d_fft_length / 2) % d_fft_length];
+ if (d_avg_min == (float)INFINITY) {
+ d_avg_min = min;
}
- else if (state == 1) {
- if (datain[i] > peak_val) {
- peak_val = datain[i];
- peak_index = i;
- d_avg = d_avg_alpha * datain[i] + (1 - d_avg_alpha) * d_avg;
- i++;
- }
- else if (datain[i] > d_avg * d_threshold_factor_fall) {
- d_avg = (d_avg_alpha) * datain[i] + (1 - d_avg_alpha) * d_avg;
- i++;
- }
- else {
- peak_pos[peak_pos_length] = peak_index;
- peak_pos_length++;
- state = 0;
- peak_val = - (float)INFINITY;
- }
+ else {
+ d_avg_min = d_avg_alpha * min + (1 - d_avg_alpha) * d_avg_min;
}
}
- // Find peak of peaks
- if (peak_pos_length) {
- float max = datain[peak_pos[0]];
- int maxi = 0;
+ if (d_avg_max == -(float)INFINITY) {
+ // Initialize d_avg_max with the first value.
+ d_avg_max = datain[peak_index];
+ }
+ else if (datain[peak_index] > d_avg_max - d_threshold_factor_rise * (d_avg_max-d_avg_min)) {
+ d_avg_max = d_avg_alpha * datain[peak_index] + (1 - d_avg_alpha) * d_avg_max;
+ }
+ else {
+ peak_pos_length = 0;
+ }
- for (int i = 1; i < peak_pos_length; i++) {
- if (datain[peak_pos[i]] > max) {
- max = datain[peak_pos[i]];
- maxi = i;
- }
+ // We now check whether the peak is in the border of the search interval. This would mean that
+ // the search interval is not correct, and it should be re-set. This happens for instance when the
+ // hardware dropped some samples.
+ // Our definition of "border of the search interval" depends if the search interval is "big" or not.
+ if (datain_length < d_fft_length) {
+ if ((peak_index == 0) || (peak_index == (unsigned int)datain_length - 1)) {
+ peak_pos_length = 0;
+ }
+ }
+ else {
+ if ((peak_index < 5) || (peak_index > (unsigned int)datain_length - 5)) {
+ peak_pos_length = 0;
}
-
- *peak_max = maxi;
}
+ peak_pos[0] = peak_index;
+ *peak_max = 0;
return (peak_pos_length);
}
@@ -119,7 +113,8 @@ namespace gr {
volk_32fc_magnitude_squared_32f(&d_norm[low], &in[low], size);
// Calculate gamma on each point
- low = lookup_stop - d_cp_length + 1;
+ // TODO check these boundaries!!!!!!!
+ low = lookup_stop - (d_cp_length - 1);
size = lookup_start - low + 1;
volk_32fc_x2_multiply_conjugate_32fc(&d_corr[low - d_fft_length], &in[low], &in[low - d_fft_length], size);
@@ -220,6 +215,12 @@ namespace gr {
this->add_item_tag(0, offset, key, value);
}
+ // Derotates the signal
+ void dvbt_ofdm_sym_acquisition_impl::derotate(const gr_complex * in, gr_complex * out)
+ {
+ volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[0], d_fft_length);
+ }
+
dvbt_ofdm_sym_acquisition::sptr
dvbt_ofdm_sym_acquisition::make(int blocks, int fft_length, int occupied_tones, int cp_length, float snr)
{
@@ -234,11 +235,10 @@ namespace gr {
: block("dvbt_ofdm_sym_acquisition",
io_signature::make(1, 1, sizeof (gr_complex) * blocks),
io_signature::make(1, 1, sizeof (gr_complex) * blocks * fft_length)),
- d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), d_snr(snr),
- d_index(0), d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_count(0), d_nextphaseinc(0), d_nextpos(0), \
- d_sym_acq_count(0),d_sym_acq_timeout(100), d_initial_acquisition(0), \
- d_freq_correction_count(0), d_freq_correction_timeout(0), d_cp_start(0), \
- d_to_consume(0), d_to_out(0)
+ d_blocks(blocks), d_fft_length(fft_length), d_cp_length(cp_length), d_snr(snr), \
+ d_phase(0.0), d_phaseinc(0.0), d_cp_found(0), d_nextphaseinc(0), d_nextpos(0), \
+ d_initial_acquisition(0), d_cp_start(0), \
+ d_to_consume(0), d_to_out(0), d_consumed(0), d_out(0)
{
set_relative_rate(1.0 / (double) (d_cp_length + d_fft_length));
@@ -296,7 +296,7 @@ namespace gr {
exit(1);
}
- peak_detect_init(0.8, 0.9, 30, 0.9);
+ peak_detect_init(0.3, 0.9);
}
/*
@@ -319,7 +319,7 @@ namespace gr {
// make sure we receive at least (symbol_length + fft_length)
for (int i = 0; i < ninputs; i++) {
- ninput_items_required[i] = (2 * d_fft_length + d_cp_length) * noutput_items;
+ ninput_items_required[i] = (d_cp_length + d_fft_length) * (noutput_items + 1);
}
}
@@ -336,45 +336,52 @@ namespace gr {
{
const gr_complex *in = (const gr_complex *) input_items[0];
gr_complex *out = (gr_complex *) output_items[0];
-
- int low, size;
-
- // This is initial acquisition of symbol start
- // TODO - make a FSM
- if (!d_initial_acquisition) {
- d_initial_acquisition = ml_sync(in, 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \
- &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
-
- // Send sync_start downstream
- send_sync_start();
- }
-
- // This is fractional frequency correction (pre FFT)
- // It is also called coarse frequency correction
- if (d_initial_acquisition) {
- d_cp_found = ml_sync(in, d_cp_start + 16, d_cp_start, \
- &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
+ int low;
+
+ d_consumed = 0;
+ d_out = 0;
+
+ for (int i = 0; i < noutput_items; i++) {
+ // This is initial acquisition of symbol start
+ // TODO - make a FSM
+ if (!d_initial_acquisition) {
+ d_initial_acquisition = ml_sync(&in[d_consumed], 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \
+ &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
+ d_cp_found = d_initial_acquisition;
+ }
+ else {
+ // If we are here it means that in the previous iteration we found the CP. We
+ // now thus only search near it.
+ d_cp_found = ml_sync(&in[d_consumed], d_cp_start + 8, std::max(d_cp_start - 8, d_cp_length+d_fft_length - 1), \
+ &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out);
+ if (!d_cp_found) {
+ // We may have not found the CP because the smaller search range was too small (rare, but possible).
+ // We re-try with the whole search range.
+ d_cp_found = ml_sync(&in[d_consumed], 2 * d_fft_length + d_cp_length - 1, d_fft_length + d_cp_length - 1, \
+ &d_cp_start, &d_derot[0], &d_to_consume, &d_to_out );
+ }
+ }
if (d_cp_found) {
- d_freq_correction_count = 0;
-
- // Derotate the signal and out
- low = d_cp_start - d_fft_length + 1;
- size = d_cp_start - (d_cp_start - d_fft_length + 1) + 1;
-
- volk_32fc_x2_multiply_32fc(&out[0], &d_derot[0], &in[low], size);
+ low = d_consumed + d_cp_start - d_fft_length + 1;
+ derotate(&in[low], &out[i * d_fft_length]);
}
else {
- // If we have a number of consecutive misses then we restart acquisition
- if (++d_freq_correction_count > d_freq_correction_timeout) {
- d_initial_acquisition = 0;
- d_freq_correction_count = 0;
-
- // Restart with a half number so that we'll not endup with the same situation
- // This will prevent peak_detect to not detect anything
- d_to_consume = d_to_consume / 2;
- }
+ // Send sync_start downstream
+ send_sync_start();
+ d_initial_acquisition = 0;
+
+ // Restart wit a half number so that we'll not end up with the same situation
+ // This will prevent peak_detect to not detect anything
+ d_to_consume = d_to_consume / 2;
+ d_consumed += d_to_consume;
+ consume_each(d_consumed);
+
+ // Tell runtime system how many output items we produced.
+ return (d_out);
}
+ d_consumed += d_to_consume;
+ d_out += d_to_out;
}
// Tell runtime system how many input items we consumed on
@@ -386,3 +393,4 @@ namespace gr {
}
} /* namespace dtv */
} /* namespace gr */
+
diff --git a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h
index e7b92cbd41..0964361b1e 100644
--- a/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h
+++ b/gr-dtv/lib/dvbt/dvbt_ofdm_sym_acquisition_impl.h
@@ -35,8 +35,6 @@ namespace gr {
float d_snr;
float d_rho;
- int d_index;
-
gr_complex * d_conj;
float * d_norm;
gr_complex * d_corr;
@@ -45,37 +43,35 @@ namespace gr {
// For peak detector
float d_threshold_factor_rise;
- float d_threshold_factor_fall;
float d_avg_alpha;
- float d_avg;
+ float d_avg_min;
+ float d_avg_max;
float d_phase;
double d_phaseinc;
int d_cp_found;
- int d_count;
double d_nextphaseinc;
int d_nextpos;
- int d_sym_acq_count;
- int d_sym_acq_timeout;
-
int d_initial_acquisition;
- int d_freq_correction_count;
- int d_freq_correction_timeout;
-
int d_cp_start;
gr_complex * d_derot;
int d_to_consume;
int d_to_out;
+ int d_consumed;
+ int d_out;
int ml_sync(const gr_complex * in, int lookup_start, int lookup_stop, int * cp_pos, gr_complex * derot, int * to_consume, int * to_out);
- int peak_detect_init(float threshold_factor_rise, float threshold_factor_fall, int look_ahead, float alpha);
+ int peak_detect_init(float threshold_factor_rise, float alpha);
int peak_detect_process(const float * datain, const int datain_length, int * peak_pos, int * peak_max);
void send_sync_start();
+
+ void derotate(const gr_complex * in, gr_complex *out);
+
public:
dvbt_ofdm_sym_acquisition_impl(int blocks, int fft_length, int occupied_tones, int cp_length, float snr);
~dvbt_ofdm_sym_acquisition_impl();
@@ -92,3 +88,4 @@ namespace gr {
} // namespace gr
#endif /* INCLUDED_DTV_DVBT_OFDM_SYM_ACQUISITION_IMPL_H */
+
diff --git a/gr-dtv/swig/dtv_swig.i b/gr-dtv/swig/dtv_swig.i
index c2fa312e05..24960bd2be 100644
--- a/gr-dtv/swig/dtv_swig.i
+++ b/gr-dtv/swig/dtv_swig.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2014,2015 Free Software Foundation, Inc.
+ * Copyright 2014,2015,2016 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -79,6 +79,11 @@
#include "gnuradio/dtv/dvbt_convolutional_deinterleaver.h"
#include "gnuradio/dtv/dvbt_reed_solomon_dec.h"
#include "gnuradio/dtv/dvbt_energy_descramble.h"
+#include "gnuradio/dtv/catv_transport_framing_enc_bb.h"
+#include "gnuradio/dtv/catv_reed_solomon_enc_bb.h"
+#include "gnuradio/dtv/catv_randomizer_bb.h"
+#include "gnuradio/dtv/catv_frame_sync_enc_bb.h"
+#include "gnuradio/dtv/catv_trellis_enc_bb.h"
%}
%include "gnuradio/dtv/atsc_deinterleaver.h"
@@ -132,6 +137,11 @@
%include "gnuradio/dtv/dvbt_convolutional_deinterleaver.h"
%include "gnuradio/dtv/dvbt_reed_solomon_dec.h"
%include "gnuradio/dtv/dvbt_energy_descramble.h"
+%include "gnuradio/dtv/catv_transport_framing_enc_bb.h"
+%include "gnuradio/dtv/catv_reed_solomon_enc_bb.h"
+%include "gnuradio/dtv/catv_randomizer_bb.h"
+%include "gnuradio/dtv/catv_frame_sync_enc_bb.h"
+%include "gnuradio/dtv/catv_trellis_enc_bb.h"
GR_SWIG_BLOCK_MAGIC2(dtv, atsc_deinterleaver);
GR_SWIG_BLOCK_MAGIC2(dtv, atsc_depad);
@@ -180,3 +190,8 @@ GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_viterbi_decoder);
GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_convolutional_deinterleaver);
GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_reed_solomon_dec);
GR_SWIG_BLOCK_MAGIC2(dtv, dvbt_energy_descramble);
+GR_SWIG_BLOCK_MAGIC2(dtv, catv_transport_framing_enc_bb);
+GR_SWIG_BLOCK_MAGIC2(dtv, catv_reed_solomon_enc_bb);
+GR_SWIG_BLOCK_MAGIC2(dtv, catv_randomizer_bb);
+GR_SWIG_BLOCK_MAGIC2(dtv, catv_frame_sync_enc_bb);
+GR_SWIG_BLOCK_MAGIC2(dtv, catv_trellis_enc_bb);
diff --git a/gr-filter/examples/synth_to_chan.py b/gr-filter/examples/synth_to_chan.py
index 9e682021b7..88fb080a65 100755
--- a/gr-filter/examples/synth_to_chan.py
+++ b/gr-filter/examples/synth_to_chan.py
@@ -54,7 +54,7 @@ def main():
fmtx = list()
for fi in freqs:
s = analog.sig_source_f(fs, analog.GR_SIN_WAVE, fi, 1)
- fm = analog.nbfm_tx(fs, 4*fs, max_dev=10000, tau=75e-6)
+ fm = analog.nbfm_tx(fs, 4*fs, max_dev=10000, tau=75e-6, fh=0.925*(4*fs)/2.0)
sigs.append(s)
fmtx.append(fm)
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc
index e282b484fd..9d1d6f6139 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.cc
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc
@@ -73,6 +73,26 @@ namespace gr {
else {
set_history(d_taps_per_filter);
}
+
+ d_tmp = NULL;
+ }
+
+ bool pfb_decimator_ccf_impl::start()
+ {
+ if(d_use_fft_filters) {
+ d_tmp = fft::malloc_complex(max_noutput_items()*d_rate);
+ }
+
+ return block::start();
+ }
+
+ bool pfb_decimator_ccf_impl::stop()
+ {
+ if((d_use_fft_filters) && (d_tmp)) {
+ fft::free(d_tmp);
+ }
+
+ return block::stop();
}
pfb_decimator_ccf_impl::~pfb_decimator_ccf_impl()
@@ -198,14 +218,13 @@ namespace gr {
gr_complex *out = (gr_complex *)output_items[0];
int i;
- gr_complex *tmp = fft::malloc_complex(noutput_items*d_rate);
// Filter each input stream by the FFT filters; do all
// noutput_items at once to avoid repeated calls to the FFT
// setup and operation.
for(unsigned int j = 0; j < d_rate; j++) {
in = (gr_complex*)input_items[d_rate-j-1];
- d_fft_filters[j]->filter(noutput_items, in, &(tmp[j*noutput_items]));
+ d_fft_filters[j]->filter(noutput_items, in, &(d_tmp[j*noutput_items]));
}
// Rotate and add filter outputs (k=channel number; M=number of
@@ -214,11 +233,10 @@ namespace gr {
for(i = 0; i < noutput_items; i++) {
out[i] = 0;
for(unsigned int j = 0; j < d_rate; j++) {
- out[i] += tmp[j*noutput_items+i]*d_rotator[j];
+ out[i] += d_tmp[j*noutput_items+i]*d_rotator[j];
}
}
- fft::free(tmp);
return noutput_items;
}
@@ -231,18 +249,17 @@ namespace gr {
gr_complex *out = (gr_complex *)output_items[0];
int i;
- gr_complex *tmp = fft::malloc_complex(noutput_items*d_rate);
for(unsigned int j = 0; j < d_rate; j++) {
in = (gr_complex*)input_items[d_rate-j-1];
- d_fft_filters[j]->filter(noutput_items, in, &tmp[j*noutput_items]);
+ d_fft_filters[j]->filter(noutput_items, in, &d_tmp[j*noutput_items]);
}
// Performs the rotate and add operations by implementing it as
// an FFT.
for(i = 0; i < noutput_items; i++) {
for(unsigned int j = 0; j < d_rate; j++) {
- d_fft->get_inbuf()[j] = tmp[j*noutput_items + i];
+ d_fft->get_inbuf()[j] = d_tmp[j*noutput_items + i];
}
// Perform the FFT to do the complex multiply despinning for all channels
@@ -252,7 +269,6 @@ namespace gr {
out[i] = d_fft->get_outbuf()[d_chan];
}
- fft::free(tmp);
return noutput_items;
}
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.h b/gr-filter/lib/pfb_decimator_ccf_impl.h
index 3397701cf9..5e0b70177d 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.h
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.h
@@ -40,6 +40,7 @@ namespace gr {
bool d_use_fft_rotator;
bool d_use_fft_filters;
gr_complex *d_rotator;
+ gr_complex *d_tmp; // used for fft filters
gr::thread::mutex d_mutex; // mutex to protect set/work access
inline int work_fir_exp(int noutput_items,
@@ -55,7 +56,6 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
-
public:
pfb_decimator_ccf_impl(unsigned int decim,
const std::vector<float> &taps,
@@ -70,6 +70,10 @@ namespace gr {
std::vector<std::vector<float> > taps() const;
void set_channel(const unsigned int channel);
+ // Overload to create/destroy d_tmp based on max_noutput_items.
+ bool start();
+ bool stop();
+
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
diff --git a/gr-qtgui/grc/qtgui_const_sink_x.xml b/gr-qtgui/grc/qtgui_const_sink_x.xml
index 956a1694ec..755f12f964 100644
--- a/gr-qtgui/grc/qtgui_const_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_const_sink_x.xml
@@ -22,6 +22,7 @@ self.$(id).set_x_axis($xmin, $xmax)
self.$(id).set_trigger_mode($tr_mode, $tr_slope, $tr_level, $tr_chan, $tr_tag)
self.$(id).enable_autoscale($autoscale)
self.$(id).enable_grid($grid)
+self.$(id).enable_axis_labels($axislabels)
if not $legend:
self.$(id).disable_legend()
@@ -276,6 +277,23 @@ $(gui_hint()($win))</make>
</param>
<param>
+ <name>Axis Labels</name>
+ <key>axislabels</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
<name>Line 1 Label</name>
<key>label1</key>
<type>string</type>
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml
index d7c3139849..009a184327 100644
--- a/gr-qtgui/grc/qtgui_freq_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -22,10 +22,12 @@ qtgui.$(type.fcn)(
)
self.$(id).set_update_time($update_time)
self.$(id).set_y_axis($ymin, $ymax)
+self.$(id).set_y_label($label, $units)
self.$(id).set_trigger_mode($tr_mode, $tr_level, $tr_chan, $tr_tag)
self.$(id).enable_autoscale($autoscale)
self.$(id).enable_grid($grid)
self.$(id).set_fft_average($average)
+self.$(id).enable_axis_labels($axislabels)
self.$(id).enable_control_panel($ctrlpanel)
if not $legend:
@@ -252,6 +254,22 @@ $(gui_hint()($win))</make>
</param>
<param>
+ <name>Y label</name>
+ <key>label</key>
+ <value>Relative Gain</value>
+ <type>string</type>
+ <hide>part</hide>
+ </param>
+
+ <param>
+ <name>Y units</name>
+ <key>units</key>
+ <value>dB</value>
+ <type>string</type>
+ <hide>part</hide>
+ </param>
+
+ <param>
<name>Number of Inputs</name>
<key>nconnections</key>
<value>1</value>
@@ -383,6 +401,23 @@ $(gui_hint()($win))</make>
</param>
<param>
+ <name>Axis Labels</name>
+ <key>axislabels</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
<name>Line 1 Label</name>
<key>label1</key>
<type>string</type>
diff --git a/gr-qtgui/grc/qtgui_histogram_sink_x.xml b/gr-qtgui/grc/qtgui_histogram_sink_x.xml
index a9966fd7ec..a789d2e4fa 100644
--- a/gr-qtgui/grc/qtgui_histogram_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_histogram_sink_x.xml
@@ -24,6 +24,7 @@ self.$(id).set_update_time($update_time)
self.$(id).enable_autoscale($autoscale)
self.$(id).enable_accumulate($accum)
self.$(id).enable_grid($grid)
+self.$(id).enable_axis_labels($axislabels)
if not $legend:
self.$(id).disable_legend()
@@ -211,6 +212,23 @@ $(gui_hint()($win))
</param>
<param>
+ <name>Axis Labels</name>
+ <key>axislabels</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
<name>Line 1 Label</name>
<key>label1</key>
<type>string</type>
diff --git a/gr-qtgui/grc/qtgui_time_raster_x.xml b/gr-qtgui/grc/qtgui_time_raster_x.xml
index b36944c1e5..0359dc3b71 100644
--- a/gr-qtgui/grc/qtgui_time_raster_x.xml
+++ b/gr-qtgui/grc/qtgui_time_raster_x.xml
@@ -24,6 +24,7 @@ qtgui.$(type.fcn)(
self.$(id).set_update_time($update_time)
self.$(id).set_intensity_range($zmin, $zmax)
self.$(id).enable_grid($grid)
+self.$(id).enable_axis_labels($axislabels)
labels = [$label1, $label2, $label3, $label4, $label5,
$label6, $label7, $label8, $label9, $label10]
@@ -185,6 +186,22 @@ $(gui_hint()($win))</make>
<hide>part</hide>
</param>
+ <param>
+ <name>Axis Labels</name>
+ <key>axislabels</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
<param>
<name>Line 1 Label</name>
diff --git a/gr-qtgui/grc/qtgui_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml
index b17b55fc48..c0584b6d34 100644
--- a/gr-qtgui/grc/qtgui_time_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_time_sink_x.xml
@@ -27,6 +27,7 @@ self.$(id).enable_tags(-1, $entags)
self.$(id).set_trigger_mode($tr_mode, $tr_slope, $tr_level, $tr_delay, $tr_chan, $tr_tag)
self.$(id).enable_autoscale($autoscale)
self.$(id).enable_grid($grid)
+self.$(id).enable_axis_labels($axislabels)
self.$(id).enable_control_panel($ctrlpanel)
if not $legend:
@@ -363,6 +364,23 @@ $(gui_hint()($win))</make>
</param>
<param>
+ <name>Axis Labels</name>
+ <key>axislabels</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
<name>Line 1 Label</name>
<key>label1</key>
<type>string</type>
diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
index 1d8461b8c4..cdecd5cce1 100644
--- a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
@@ -22,6 +22,7 @@ qtgui.$(type.fcn)(
)
self.$(id).set_update_time($update_time)
self.$(id).enable_grid($grid)
+self.$(id).enable_axis_labels($axislabels)
if not $legend:
self.$(id).disable_legend()
@@ -271,6 +272,23 @@ $(gui_hint()($win))</make>
</param>
<param>
+ <name>Axis Labels</name>
+ <key>axislabels</key>
+ <value>True</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Yes</name>
+ <key>True</key>
+ </option>
+ <option>
+ <name>No</name>
+ <key>False</key>
+ </option>
+ <tab>Config</tab>
+ </param>
+
+ <param>
<name>Line 1 Color</name>
<key>color1</key>
<type>enum</type>
diff --git a/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h b/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
index 9edff7b183..eba12e2635 100644
--- a/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
+++ b/gr-qtgui/include/gnuradio/qtgui/DisplayPlot.h
@@ -190,6 +190,7 @@ public:
public slots:
virtual void disableLegend();
+ virtual void setAxisLabels(bool en);
virtual void setYaxis(double min, double max);
virtual void setXaxis(double min, double max);
virtual void setLineLabel(int which, QString label);
diff --git a/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h b/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
index 8b2ef457fb..5c6b2c71b0 100644
--- a/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
+++ b/gr-qtgui/include/gnuradio/qtgui/FrequencyDisplayPlot.h
@@ -118,6 +118,9 @@ public slots:
void setPlotPosHalf(bool half);
+ void setYLabel(const std::string &label,
+ const std::string &unit);
+
void clearMaxData();
void clearMinData();
diff --git a/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
index 851f3be7ca..9905eb7690 100644
--- a/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
@@ -144,6 +144,7 @@ namespace gr {
virtual void enable_menu(bool en=true) = 0;
virtual void enable_autoscale(bool en) = 0;
virtual void enable_grid(bool en) = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
virtual void disable_legend() = 0;
virtual int nsamps() const = 0;
virtual void reset() = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/displayform.h b/gr-qtgui/include/gnuradio/qtgui/displayform.h
index 2ef4b801cf..1da1383370 100644
--- a/gr-qtgui/include/gnuradio/qtgui/displayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/displayform.h
@@ -83,6 +83,7 @@ public slots:
void setStop();
void setGrid(bool on);
+ void setAxisLabels(bool en);
void saveFigure();
@@ -117,6 +118,8 @@ protected:
bool d_stop_state;
QAction *d_grid_act;
bool d_grid_state;
+ QAction *d_axislabelsmenu;
+ bool d_axislabels;
QAction *d_autoscale_act;
bool d_autoscale_state;
diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
index bf5a91f0df..3aea2d1b84 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_c.h
@@ -128,6 +128,7 @@ namespace gr {
virtual void set_update_time(double t) = 0;
virtual void set_title(const std::string &title) = 0;
+ virtual void set_y_label(const std::string &label, const std::string &unit) = 0;
virtual void set_line_label(int which, const std::string &label) = 0;
virtual void set_line_color(int which, const std::string &color) = 0;
virtual void set_line_width(int which, int width) = 0;
@@ -182,6 +183,7 @@ namespace gr {
virtual void clear_min_hold() = 0;
virtual void disable_legend() = 0;
virtual void reset() = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
QApplication *d_qApplication;
};
diff --git a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
index f13d5c6e40..eb68806c07 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freq_sink_f.h
@@ -126,7 +126,9 @@ namespace gr {
virtual void set_y_axis(double min, double max) = 0;
virtual void set_update_time(double t) = 0;
+
virtual void set_title(const std::string &title) = 0;
+ virtual void set_y_label(const std::string &label, const std::string &unit) = 0;
virtual void set_line_label(int which, const std::string &label) = 0;
virtual void set_line_color(int which, const std::string &color) = 0;
virtual void set_line_width(int which, int width) = 0;
@@ -188,6 +190,7 @@ namespace gr {
virtual void clear_min_hold() = 0;
virtual void disable_legend() = 0;
virtual void reset() = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
QApplication *d_qApplication;
};
diff --git a/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h b/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h
index ce0aeedf9f..ec3ef6cfd1 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freqcontrolpanel.h
@@ -76,6 +76,7 @@ private:
QVBoxLayout *d_axes_layout;
QCheckBox *d_grid_check;
+ QCheckBox *d_axislabels_check;
QHBoxLayout *d_yrange_layout;
QLabel *d_yrange_label;
QPushButton *d_yrange_plus;
diff --git a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
index e7b95cb30e..4d8ed3e2a1 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
@@ -75,6 +75,8 @@ public slots:
void setFrequencyRange(const double centerfreq,
const double bandwidth);
void setYaxis(double min, double max);
+ void setYLabel(const std::string &label,
+ const std::string &unit="");
void setYMax(const QString &m);
void setYMin(const QString &m);
void autoScale(bool en);
@@ -108,7 +110,6 @@ public slots:
void notifyTriggerLevelPlus();
void notifyTriggerLevelMinus();
-
signals:
void signalFFTSize(int size);
void signalFFTWindow(gr::filter::firdes::win_type win);
diff --git a/gr-qtgui/include/gnuradio/qtgui/histogram_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/histogram_sink_f.h
index 431941a414..6e7dee005d 100644
--- a/gr-qtgui/include/gnuradio/qtgui/histogram_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/histogram_sink_f.h
@@ -121,6 +121,7 @@ namespace gr {
virtual void enable_semilogx(bool en=true) = 0;
virtual void enable_semilogy(bool en=true) = 0;
virtual void enable_accumulate(bool en=true) = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
virtual void autoscalex() = 0;
virtual int nsamps() const = 0;
virtual int bins() const = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_b.h b/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_b.h
index ed55e2ed50..efaef1cc4b 100644
--- a/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_b.h
+++ b/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_b.h
@@ -131,6 +131,7 @@ namespace gr {
virtual void enable_menu(bool en) = 0;
virtual void enable_grid(bool en) = 0;
virtual void enable_autoscale(bool en) = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
virtual void reset() = 0;
QApplication *d_qApplication;
diff --git a/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_f.h
index 5610dabdda..ae2ec8d11b 100644
--- a/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/time_raster_sink_f.h
@@ -127,6 +127,7 @@ namespace gr {
virtual void enable_menu(bool en) = 0;
virtual void enable_grid(bool en) = 0;
virtual void enable_autoscale(bool en) = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
virtual void reset() = 0;
QApplication *d_qApplication;
diff --git a/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
index 10c87c8bf2..af921afc1b 100644
--- a/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
@@ -170,6 +170,7 @@ namespace gr {
virtual void enable_semilogy(bool en=true) = 0;
virtual void enable_control_panel(bool en=true) = 0;
virtual void enable_tags(int which, bool en) = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
virtual void disable_legend() = 0;
virtual int nsamps() const = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
index d96383c0e8..7ddca46297 100644
--- a/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
@@ -160,6 +160,7 @@ namespace gr {
virtual void enable_semilogy(bool en=true) = 0;
virtual void enable_control_panel(bool en=true) = 0;
virtual void enable_tags(int which, bool en) = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
virtual void disable_legend() = 0;
virtual int nsamps() const = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/timecontrolpanel.h b/gr-qtgui/include/gnuradio/qtgui/timecontrolpanel.h
index aabd890e6e..d7cbf5431b 100644
--- a/gr-qtgui/include/gnuradio/qtgui/timecontrolpanel.h
+++ b/gr-qtgui/include/gnuradio/qtgui/timecontrolpanel.h
@@ -75,6 +75,8 @@ private:
QCheckBox *d_autoscale_check;
QCheckBox *d_grid_check;
+ QCheckBox *d_axislabels_check;
+
QPushButton *d_yoff_plus, *d_yoff_minus;
QPushButton *d_yrange_plus, *d_yrange_minus;
QPushButton *d_xmax_plus, *d_xmax_minus;
diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h
index 71a8b925bb..1e4073aa01 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_c.h
@@ -156,6 +156,7 @@ namespace gr {
virtual void enable_menu(bool en=true) = 0;
virtual void enable_grid(bool en=true) = 0;
virtual void disable_legend() = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
QApplication *d_qApplication;
};
diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h
index 2a51fba865..93c93bdd5e 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfall_sink_f.h
@@ -164,6 +164,7 @@ namespace gr {
virtual void enable_menu(bool en=true) = 0;
virtual void enable_grid(bool en=true) = 0;
virtual void disable_legend() = 0;
+ virtual void enable_axis_labels(bool en=true) = 0;
QApplication *d_qApplication;
};
diff --git a/gr-qtgui/lib/DisplayPlot.cc b/gr-qtgui/lib/DisplayPlot.cc
index 30fd837772..59384c88f6 100644
--- a/gr-qtgui/lib/DisplayPlot.cc
+++ b/gr-qtgui/lib/DisplayPlot.cc
@@ -443,3 +443,12 @@ DisplayPlot::onPickerPointSelected6(const QPointF & p)
//fprintf(stderr,"onPickerPointSelected %f %f\n", point.x(), point.y());
emit plotPointSelected(point);
}
+
+void
+DisplayPlot::setAxisLabels(bool en)
+{
+ enableAxis(0,en);
+ enableAxis(2,en);
+}
+
+
diff --git a/gr-qtgui/lib/FrequencyDisplayPlot.cc b/gr-qtgui/lib/FrequencyDisplayPlot.cc
index aef975d332..233c786d0a 100644
--- a/gr-qtgui/lib/FrequencyDisplayPlot.cc
+++ b/gr-qtgui/lib/FrequencyDisplayPlot.cc
@@ -97,7 +97,7 @@ FrequencyDisplayPlot::FrequencyDisplayPlot(int nplots, QWidget* parent)
d_ymax = 10;
setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
setAxisScale(QwtPlot::yLeft, d_ymin, d_ymax);
- setAxisTitle(QwtPlot::yLeft, "Power (dB)");
+ setAxisTitle(QwtPlot::yLeft, "Relative Gain (dB)");
QList<QColor> default_colors;
default_colors << QColor(Qt::blue) << QColor(Qt::red) << QColor(Qt::green)
@@ -600,6 +600,17 @@ FrequencyDisplayPlot::onPickerPointSelected6(const QPointF & p)
}
void
+FrequencyDisplayPlot::setYLabel(const std::string &label,
+ const std::string &unit)
+{
+ std::string l = label;
+ if(unit.length() > 0)
+ l += " (" + unit + ")";
+ setAxisTitle(QwtPlot::yLeft, QString(l.c_str()));
+ ((FreqDisplayZoomer*)d_zoomer)->setUnitType(unit);
+}
+
+void
FrequencyDisplayPlot::setMinFFTColor (QColor c)
{
d_min_fft_color = c;
diff --git a/gr-qtgui/lib/WaterfallDisplayPlot.cc b/gr-qtgui/lib/WaterfallDisplayPlot.cc
index 676e4077db..b16c32bf9d 100644
--- a/gr-qtgui/lib/WaterfallDisplayPlot.cc
+++ b/gr-qtgui/lib/WaterfallDisplayPlot.cc
@@ -657,8 +657,6 @@ WaterfallDisplayPlot::_updateIntensityRangeDisplay()
setAxisScale(QwtPlot::yRight, intv.minValue(), intv.maxValue());
#endif
- enableAxis(d_legend_enabled);
-
plotLayout()->setAlignCanvasToScales(true);
// Tell the display to redraw everything
diff --git a/gr-qtgui/lib/const_sink_c_impl.cc b/gr-qtgui/lib/const_sink_c_impl.cc
index 7ef8db393d..eaaf5f570a 100644
--- a/gr-qtgui/lib/const_sink_c_impl.cc
+++ b/gr-qtgui/lib/const_sink_c_impl.cc
@@ -375,6 +375,12 @@ namespace gr {
}
void
+ const_sink_c_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
const_sink_c_impl::disable_legend()
{
d_main_gui->disableLegend();
diff --git a/gr-qtgui/lib/const_sink_c_impl.h b/gr-qtgui/lib/const_sink_c_impl.h
index 7d52c3ae15..f2dcb6e73e 100644
--- a/gr-qtgui/lib/const_sink_c_impl.h
+++ b/gr-qtgui/lib/const_sink_c_impl.h
@@ -118,6 +118,7 @@ namespace gr {
void enable_menu(bool en);
void enable_autoscale(bool en);
void enable_grid(bool en);
+ void enable_axis_labels(bool en);
void disable_legend();
void reset();
diff --git a/gr-qtgui/lib/displayform.cc b/gr-qtgui/lib/displayform.cc
index 27a09512fc..13c2d8a193 100644
--- a/gr-qtgui/lib/displayform.cc
+++ b/gr-qtgui/lib/displayform.cc
@@ -29,6 +29,7 @@ DisplayForm::DisplayForm(int nplots, QWidget* parent)
: QWidget(parent), d_nplots(nplots), d_system_specified_flag(false)
{
d_isclosed = false;
+ d_axislabels = true;
// Set the initial plot size
resize(QSize(800, 600));
@@ -53,11 +54,18 @@ DisplayForm::DisplayForm(int nplots, QWidget* parent)
this, SLOT(setGrid(bool)));
d_grid_state = false;
+ d_axislabelsmenu = new QAction("Axis Labels", this);
+ d_axislabelsmenu->setCheckable(true);
+ d_axislabelsmenu->setStatusTip(tr("Toggle Axis Labels on/off"));
+ connect(d_axislabelsmenu, SIGNAL(triggered(bool)),
+ this, SLOT(setAxisLabels(bool)));
+
// Create a pop-up menu for manipulating the figure
d_menu_on = true;
d_menu = new QMenu(this);
d_menu->addAction(d_stop_act);
d_menu->addAction(d_grid_act);
+ d_menu->addAction(d_axislabelsmenu);
for(int i = 0; i < d_nplots; i++) {
d_line_title_act.push_back(new LineTitleAction(i, this));
@@ -339,6 +347,14 @@ DisplayForm::setGrid(bool on)
}
void
+DisplayForm::setAxisLabels(bool en)
+{
+ d_axislabels = en;
+ d_axislabelsmenu->setChecked(en);
+ getPlot()->setAxisLabels(d_axislabels);
+}
+
+void
DisplayForm::saveFigure()
{
QPixmap qpix = QPixmap::grabWidget(this);
diff --git a/gr-qtgui/lib/freq_sink_c_impl.cc b/gr-qtgui/lib/freq_sink_c_impl.cc
index 7dc0b2cf89..517786d58d 100644
--- a/gr-qtgui/lib/freq_sink_c_impl.cc
+++ b/gr-qtgui/lib/freq_sink_c_impl.cc
@@ -266,6 +266,13 @@ namespace gr {
}
void
+ freq_sink_c_impl::set_y_label(const std::string &label,
+ const std::string &unit)
+ {
+ d_main_gui->setYLabel(label, unit);
+ }
+
+ void
freq_sink_c_impl::set_update_time(double t)
{
//convert update time to ticks
@@ -407,6 +414,12 @@ namespace gr {
}
void
+ freq_sink_c_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
freq_sink_c_impl::enable_control_panel(bool en)
{
if(en)
diff --git a/gr-qtgui/lib/freq_sink_c_impl.h b/gr-qtgui/lib/freq_sink_c_impl.h
index 8da193bf29..b102209359 100644
--- a/gr-qtgui/lib/freq_sink_c_impl.h
+++ b/gr-qtgui/lib/freq_sink_c_impl.h
@@ -123,6 +123,7 @@ namespace gr {
void set_update_time(double t);
void set_title(const std::string &title);
+ void set_y_label(const std::string &label, const std::string &unit);
void set_line_label(int which, const std::string &label);
void set_line_color(int which, const std::string &color);
void set_line_width(int which, int width);
@@ -153,6 +154,7 @@ namespace gr {
void clear_min_hold();
void disable_legend();
void reset();
+ void enable_axis_labels(bool en);
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-qtgui/lib/freq_sink_f_impl.cc b/gr-qtgui/lib/freq_sink_f_impl.cc
index 5418eca9ec..90624e78eb 100644
--- a/gr-qtgui/lib/freq_sink_f_impl.cc
+++ b/gr-qtgui/lib/freq_sink_f_impl.cc
@@ -265,6 +265,13 @@ namespace gr {
}
void
+ freq_sink_f_impl::set_y_label(const std::string &label,
+ const std::string &unit)
+ {
+ d_main_gui->setYLabel(label, unit);
+ }
+
+ void
freq_sink_f_impl::set_update_time(double t)
{
//convert update time to ticks
@@ -412,6 +419,12 @@ namespace gr {
}
void
+ freq_sink_f_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
freq_sink_f_impl::enable_control_panel(bool en)
{
if(en)
diff --git a/gr-qtgui/lib/freq_sink_f_impl.h b/gr-qtgui/lib/freq_sink_f_impl.h
index 39e5c92eac..85d45b3f4c 100644
--- a/gr-qtgui/lib/freq_sink_f_impl.h
+++ b/gr-qtgui/lib/freq_sink_f_impl.h
@@ -122,6 +122,7 @@ namespace gr {
void set_update_time(double t);
void set_title(const std::string &title);
+ void set_y_label(const std::string &label, const std::string &unit);
void set_line_label(int which, const std::string &label);
void set_line_color(int which, const std::string &color);
void set_line_width(int which, int width);
@@ -153,6 +154,7 @@ namespace gr {
void clear_min_hold();
void disable_legend();
void reset();
+ void enable_axis_labels(bool en);
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-qtgui/lib/freqcontrolpanel.cc b/gr-qtgui/lib/freqcontrolpanel.cc
index 5840989949..9729005f50 100644
--- a/gr-qtgui/lib/freqcontrolpanel.cc
+++ b/gr-qtgui/lib/freqcontrolpanel.cc
@@ -50,6 +50,7 @@ FreqControlPanel::FreqControlPanel(FreqDisplayForm *form)
d_axes_layout = new QVBoxLayout;
d_grid_check = new QCheckBox("Grid");
+ d_axislabels_check = new QCheckBox("Axis Labels");
d_yrange_layout = new QHBoxLayout;
d_yrange_label = new QLabel("Y Range:");
d_yrange_plus = new QPushButton("+");
@@ -133,6 +134,7 @@ FreqControlPanel::FreqControlPanel(FreqDisplayForm *form)
d_trace_box->setLayout(d_trace_layout);
d_axes_layout->addWidget(d_grid_check);
+ d_axes_layout->addWidget(d_axislabels_check);
d_axes_layout->addLayout(d_yrange_layout);
d_axes_layout->addLayout(d_ymin_layout);
d_axes_layout->addWidget(d_autoscale_button);
@@ -171,6 +173,9 @@ FreqControlPanel::FreqControlPanel(FreqDisplayForm *form)
connect(d_grid_check, SIGNAL(clicked(bool)),
d_parent, SLOT(setGrid(bool)));
+ connect(d_axislabels_check, SIGNAL(clicked(bool)),
+ d_parent, SLOT(setAxisLabels(bool)));
+
connect(d_ymin_plus, SIGNAL(pressed(void)),
d_parent, SLOT(notifyYAxisPlus(void)));
connect(d_ymin_minus, SIGNAL(pressed(void)),
diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc
index a51da3f35d..141df5475c 100644
--- a/gr-qtgui/lib/freqdisplayform.cc
+++ b/gr-qtgui/lib/freqdisplayform.cc
@@ -323,6 +323,12 @@ FreqDisplayForm::setYaxis(double min, double max)
getPlot()->setYaxis(min, max);
}
+void FreqDisplayForm::setYLabel(const std::string &label,
+ const std::string &unit)
+{
+ getPlot()->setYLabel(label, unit);
+}
+
void
FreqDisplayForm::setYMax(const QString &m)
{
diff --git a/gr-qtgui/lib/histogram_sink_f_impl.cc b/gr-qtgui/lib/histogram_sink_f_impl.cc
index 0ac494d751..4a1267c129 100644
--- a/gr-qtgui/lib/histogram_sink_f_impl.cc
+++ b/gr-qtgui/lib/histogram_sink_f_impl.cc
@@ -346,6 +346,12 @@ namespace gr {
}
void
+ histogram_sink_f_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
histogram_sink_f_impl::enable_autoscale(bool en)
{
d_main_gui->autoScale(en);
diff --git a/gr-qtgui/lib/histogram_sink_f_impl.h b/gr-qtgui/lib/histogram_sink_f_impl.h
index acacf1a745..d397beeb6b 100644
--- a/gr-qtgui/lib/histogram_sink_f_impl.h
+++ b/gr-qtgui/lib/histogram_sink_f_impl.h
@@ -88,6 +88,7 @@ namespace gr {
void set_line_alpha(int which, double alpha);
void set_nsamps(const int newsize);
void set_bins(const int bins);
+ void enable_axis_labels(bool en);
std::string title();
std::string line_label(int which);
diff --git a/gr-qtgui/lib/time_raster_sink_b_impl.cc b/gr-qtgui/lib/time_raster_sink_b_impl.cc
index 26fed4b062..c0990a9890 100644
--- a/gr-qtgui/lib/time_raster_sink_b_impl.cc
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.cc
@@ -418,6 +418,12 @@ namespace gr {
}
void
+ time_raster_sink_b_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
time_raster_sink_b_impl::enable_autoscale(bool en)
{
d_main_gui->autoScale(en);
diff --git a/gr-qtgui/lib/time_raster_sink_b_impl.h b/gr-qtgui/lib/time_raster_sink_b_impl.h
index 4da6990a18..48037b5e5e 100644
--- a/gr-qtgui/lib/time_raster_sink_b_impl.h
+++ b/gr-qtgui/lib/time_raster_sink_b_impl.h
@@ -122,6 +122,7 @@ namespace gr {
void enable_menu(bool en);
void enable_grid(bool en);
void enable_autoscale(bool en);
+ void enable_axis_labels(bool en);
void reset();
int work(int noutput_items,
diff --git a/gr-qtgui/lib/time_raster_sink_f_impl.cc b/gr-qtgui/lib/time_raster_sink_f_impl.cc
index 419d52cad6..2fb3e7db68 100644
--- a/gr-qtgui/lib/time_raster_sink_f_impl.cc
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.cc
@@ -408,6 +408,12 @@ namespace gr {
}
void
+ time_raster_sink_f_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
time_raster_sink_f_impl::enable_autoscale(bool en)
{
d_main_gui->autoScale(en);
diff --git a/gr-qtgui/lib/time_raster_sink_f_impl.h b/gr-qtgui/lib/time_raster_sink_f_impl.h
index ad63e4d777..1f25dc5534 100644
--- a/gr-qtgui/lib/time_raster_sink_f_impl.h
+++ b/gr-qtgui/lib/time_raster_sink_f_impl.h
@@ -121,6 +121,7 @@ namespace gr {
void enable_menu(bool en);
void enable_grid(bool en);
void enable_autoscale(bool en);
+ void enable_axis_labels(bool en);
void reset();
int work(int noutput_items,
diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc
index fff12b070a..98f603a8b0 100644
--- a/gr-qtgui/lib/time_sink_c_impl.cc
+++ b/gr-qtgui/lib/time_sink_c_impl.cc
@@ -441,10 +441,16 @@ namespace gr {
d_main_gui->setTagMenu(which, en);
}
+ void
+ time_sink_c_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
void
time_sink_c_impl::disable_legend()
{
- d_main_gui->disableLegend();
+ d_main_gui->disableLegend();
}
void
diff --git a/gr-qtgui/lib/time_sink_c_impl.h b/gr-qtgui/lib/time_sink_c_impl.h
index ce6bd94d51..ff938f8ea1 100644
--- a/gr-qtgui/lib/time_sink_c_impl.h
+++ b/gr-qtgui/lib/time_sink_c_impl.h
@@ -130,6 +130,7 @@ namespace gr {
void enable_semilogy(bool en);
void enable_control_panel(bool en);
void enable_tags(int which, bool en);
+ void enable_axis_labels(bool en);
void disable_legend();
void reset();
diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc
index 579dfd9906..50a86d7dff 100644
--- a/gr-qtgui/lib/time_sink_f_impl.cc
+++ b/gr-qtgui/lib/time_sink_f_impl.cc
@@ -437,6 +437,12 @@ namespace gr {
}
void
+ time_sink_f_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
time_sink_f_impl::disable_legend()
{
d_main_gui->disableLegend();
diff --git a/gr-qtgui/lib/time_sink_f_impl.h b/gr-qtgui/lib/time_sink_f_impl.h
index 25d920c0da..a7a304aee1 100644
--- a/gr-qtgui/lib/time_sink_f_impl.h
+++ b/gr-qtgui/lib/time_sink_f_impl.h
@@ -130,6 +130,7 @@ namespace gr {
void enable_semilogy(bool en);
void enable_control_panel(bool en);
void enable_tags(int which, bool en);
+ void enable_axis_labels(bool en);
void disable_legend();
void reset();
diff --git a/gr-qtgui/lib/timecontrolpanel.cc b/gr-qtgui/lib/timecontrolpanel.cc
index 4c5a718f97..95d2cb7a1c 100644
--- a/gr-qtgui/lib/timecontrolpanel.cc
+++ b/gr-qtgui/lib/timecontrolpanel.cc
@@ -31,6 +31,8 @@ TimeControlPanel::TimeControlPanel(TimeDisplayForm *form)
d_axes_layout = new QVBoxLayout;
d_autoscale_check = new QCheckBox("Autoscale");
d_grid_check = new QCheckBox("Grid");
+ d_axislabels_check = new QCheckBox("Axis Labels");
+ d_axislabels_check->setChecked(true);
d_yoff_layout = new QHBoxLayout;
d_yoff_label = new QLabel("Y Offset:");
@@ -106,6 +108,7 @@ TimeControlPanel::TimeControlPanel(TimeDisplayForm *form)
// Set up the boxes into the layout
d_axes_layout->addWidget(d_autoscale_check);
d_axes_layout->addWidget(d_grid_check);
+ d_axes_layout->addWidget(d_axislabels_check);
d_axes_layout->addLayout(d_yoff_layout);
d_axes_layout->addLayout(d_yrange_layout);
d_axes_layout->addLayout(d_xmax_layout);
@@ -132,6 +135,8 @@ TimeControlPanel::TimeControlPanel(TimeDisplayForm *form)
d_parent, SLOT(autoScale(bool)));
connect(d_grid_check, SIGNAL(clicked(bool)),
d_parent, SLOT(setGrid(bool)));
+ connect(d_axislabels_check, SIGNAL(clicked(bool)),
+ d_parent, SLOT(setAxisLabels(bool)));
connect(d_yoff_plus, SIGNAL(pressed(void)),
d_parent, SLOT(notifyYAxisPlus(void)));
connect(d_yoff_minus, SIGNAL(pressed(void)),
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.cc b/gr-qtgui/lib/waterfall_sink_c_impl.cc
index 694ef4dac7..7395aaf2a9 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.cc
@@ -368,6 +368,12 @@ namespace gr {
}
void
+ waterfall_sink_c_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
waterfall_sink_c_impl::disable_legend()
{
d_main_gui->disableLegend();
diff --git a/gr-qtgui/lib/waterfall_sink_c_impl.h b/gr-qtgui/lib/waterfall_sink_c_impl.h
index 3e7f9ddd2d..49766cd3dc 100644
--- a/gr-qtgui/lib/waterfall_sink_c_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_c_impl.h
@@ -132,6 +132,7 @@ namespace gr {
void enable_menu(bool en);
void enable_grid(bool en);
void disable_legend();
+ void enable_axis_labels(bool en);
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.cc b/gr-qtgui/lib/waterfall_sink_f_impl.cc
index 56c2061f25..b6f50de31d 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.cc
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.cc
@@ -374,6 +374,12 @@ namespace gr {
}
void
+ waterfall_sink_f_impl::enable_axis_labels(bool en)
+ {
+ d_main_gui->setAxisLabels(en);
+ }
+
+ void
waterfall_sink_f_impl::disable_legend()
{
d_main_gui->disableLegend();
diff --git a/gr-qtgui/lib/waterfall_sink_f_impl.h b/gr-qtgui/lib/waterfall_sink_f_impl.h
index e4f855c9f5..db0f4239bc 100644
--- a/gr-qtgui/lib/waterfall_sink_f_impl.h
+++ b/gr-qtgui/lib/waterfall_sink_f_impl.h
@@ -133,6 +133,7 @@ namespace gr {
void enable_menu(bool en);
void enable_grid(bool en);
void disable_legend();
+ void enable_axis_labels(bool en);
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-uhd/apps/uhd_app.py b/gr-uhd/apps/uhd_app.py
index 59bebe24ec..ff4412a140 100644
--- a/gr-uhd/apps/uhd_app.py
+++ b/gr-uhd/apps/uhd_app.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2015 Free Software Foundation, Inc.
+# Copyright 2015-2016 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -141,6 +141,9 @@ class UHDApp(object):
if args.spec:
for mb_idx in xrange(self.usrp.get_num_mboards()):
self.usrp.set_subdev_spec(args.spec, mb_idx)
+ # Set the clock source:
+ if args.clock_source is not None:
+ self.usrp.set_clock_source(args.clock_source)
# Sampling rate:
self.usrp.set_samp_rate(args.samp_rate)
self.samp_rate = self.usrp.get_samp_rate()
@@ -305,5 +308,7 @@ class UHDApp(object):
help="Show asynchronous message notifications from UHD")
group.add_argument("--sync", choices=('default', 'pps', 'auto'),
default='auto', help="Set to 'pps' to sync devices to PPS")
+ group.add_argument("--clock-source",
+ help="Set the clock source; typically 'internal', 'external' or 'gpsdo'")
return parser
diff --git a/gr-uhd/examples/python/fm_tx4.py b/gr-uhd/examples/python/fm_tx4.py
index fefa67861b..516033dae1 100755
--- a/gr-uhd/examples/python/fm_tx4.py
+++ b/gr-uhd/examples/python/fm_tx4.py
@@ -63,7 +63,8 @@ class pipeline(gr.hier_block2):
sys.exit(1)
print audio_rate, if_rate
- fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3, tau=75e-6)
+ fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3,
+ tau=75e-6, fh=0.925*if_rate/2.0)
# Local oscillator
lo = analog.sig_source_c(if_rate, # sample rate
diff --git a/gr-uhd/include/gnuradio/uhd/usrp_source.h b/gr-uhd/include/gnuradio/uhd/usrp_source.h
index 19b3feb61f..19201c031c 100644
--- a/gr-uhd/include/gnuradio/uhd/usrp_source.h
+++ b/gr-uhd/include/gnuradio/uhd/usrp_source.h
@@ -96,10 +96,13 @@ namespace gr {
/*!
* \param device_addr the address to identify the hardware
* \param stream_args the IO format and channel specification
+ * \param issue_stream_cmd_on_start enable or disable continuous streaming when flowgraph
+ * starts (default true)
* \return a new USRP source block object
*/
static sptr make(const ::uhd::device_addr_t &device_addr,
- const ::uhd::stream_args_t &stream_args);
+ const ::uhd::stream_args_t &stream_args,
+ const bool issue_stream_cmd_on_start = true);
/*!
* Set the start time for incoming samples.
diff --git a/gr-uhd/lib/usrp_source_impl.cc b/gr-uhd/lib/usrp_source_impl.cc
index eeb9521a5a..7ad2280955 100644
--- a/gr-uhd/lib/usrp_source_impl.cc
+++ b/gr-uhd/lib/usrp_source_impl.cc
@@ -53,20 +53,23 @@ namespace gr {
usrp_source::sptr
usrp_source::make(const ::uhd::device_addr_t &device_addr,
- const ::uhd::stream_args_t &stream_args)
+ const ::uhd::stream_args_t &stream_args,
+ const bool issue_stream_cmd_on_start)
{
check_abi();
return usrp_source::sptr
- (new usrp_source_impl(device_addr, stream_args_ensure(stream_args)));
+ (new usrp_source_impl(device_addr, stream_args_ensure(stream_args), issue_stream_cmd_on_start));
}
usrp_source_impl::usrp_source_impl(const ::uhd::device_addr_t &device_addr,
- const ::uhd::stream_args_t &stream_args):
+ const ::uhd::stream_args_t &stream_args,
+ const bool issue_stream_cmd_on_start):
usrp_block("gr uhd usrp source",
io_signature::make(0, 0, 0),
args_to_io_sig(stream_args)),
usrp_block_impl(device_addr, stream_args, ""),
- _tag_now(false)
+ _tag_now(false),
+ _issue_stream_cmd_on_start(issue_stream_cmd_on_start)
{
std::stringstream str;
str << name() << unique_id();
@@ -382,18 +385,20 @@ namespace gr {
_samps_per_packet = _rx_stream->get_max_num_samps();
}
#endif
- //setup a stream command that starts streaming slightly in the future
- static const double reasonable_delay = 0.1; //order of magnitude over RTT
- ::uhd::stream_cmd_t stream_cmd(::uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
- stream_cmd.stream_now = _stream_now;
- if(_start_time_set) {
- _start_time_set = false; //cleared for next run
- stream_cmd.time_spec = _start_time;
- }
- else {
- stream_cmd.time_spec = get_time_now() + ::uhd::time_spec_t(reasonable_delay);
+ if(_issue_stream_cmd_on_start){
+ //setup a stream command that starts streaming slightly in the future
+ static const double reasonable_delay = 0.1; //order of magnitude over RTT
+ ::uhd::stream_cmd_t stream_cmd(::uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
+ stream_cmd.stream_now = _stream_now;
+ if(_start_time_set) {
+ _start_time_set = false; //cleared for next run
+ stream_cmd.time_spec = _start_time;
+ }
+ else {
+ stream_cmd.time_spec = get_time_now() + ::uhd::time_spec_t(reasonable_delay);
+ }
+ this->issue_stream_cmd(stream_cmd);
}
- this->issue_stream_cmd(stream_cmd);
_tag_now = true;
return true;
}
diff --git a/gr-uhd/lib/usrp_source_impl.h b/gr-uhd/lib/usrp_source_impl.h
index 98af816c02..b43df4dab3 100644
--- a/gr-uhd/lib/usrp_source_impl.h
+++ b/gr-uhd/lib/usrp_source_impl.h
@@ -55,7 +55,8 @@ namespace gr {
{
public:
usrp_source_impl(const ::uhd::device_addr_t &device_addr,
- const ::uhd::stream_args_t &stream_args);
+ const ::uhd::stream_args_t &stream_args,
+ const bool issue_stream_cmd_on_start = true);
~usrp_source_impl();
// Get Commands
@@ -119,6 +120,7 @@ namespace gr {
bool _tag_now;
::uhd::rx_metadata_t _metadata;
pmt::pmt_t _id;
+ bool _issue_stream_cmd_on_start;
//tag shadows
double _samp_rate;
diff --git a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt
index 9b41b99f14..6f32f21833 100644
--- a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt
+++ b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt
@@ -24,6 +24,12 @@ cmake_minimum_required(VERSION 2.6)
project(gr-howto CXX C)
enable_testing()
+#install to PyBOMBS target prefix if defined
+if(DEFINED ENV{PYBOMBS_PREFIX})
+ set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX})
+ message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}")
+endif()
+
#select the release build type by default to get optimization flags
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
diff --git a/gr-utils/python/modtool/modtool_add.py b/gr-utils/python/modtool/modtool_add.py
index a4812c8105..3627dc6ad1 100644
--- a/gr-utils/python/modtool/modtool_add.py
+++ b/gr-utils/python/modtool/modtool_add.py
@@ -53,6 +53,8 @@ class ModToolAdd(ModTool):
choices=self._block_types, default=None, help="One of %s." % ', '.join(self._block_types))
ogroup.add_option("--license-file", type="string", default=None,
help="File containing the license header for every source code file.")
+ ogroup.add_option("--copyright", type="string", default=None,
+ help="Name of the copyright holder (you or your company) MUST be a quoted string.")
ogroup.add_option("--argument-list", type="string", default=None,
help="The argument list for the constructor and make functions.")
ogroup.add_option("--add-python-qa", action="store_true", default=None,
@@ -77,7 +79,6 @@ class ModToolAdd(ModTool):
self._info['blocktype'] = raw_input("Enter block type: ")
if self._info['blocktype'] not in self._block_types:
print 'Must be one of ' + str(self._block_types)
-
# Allow user to specify language interactively if not set
self._info['lang'] = options.lang
if self._info['lang'] is None:
@@ -102,8 +103,14 @@ class ModToolAdd(ModTool):
raise ModToolException('Invalid block name.')
print "Block/code identifier: " + self._info['blockname']
self._info['fullblockname'] = self._info['modname'] + '_' + self._info['blockname']
+ if not options.license_file:
+ self._info['copyrightholder'] = options.copyright
+ if self._info['copyrightholder'] is None:
+ self._info['copyrightholder'] = '<+YOU OR YOUR COMPANY+>'
+ elif self._info['is_component']:
+ print "For GNU Radio components the FSF is added as copyright holder"
+ self._license_file = options.license_file
self._info['license'] = self.setup_choose_license()
-
if options.argument_list is not None:
self._info['arglist'] = options.argument_list
else:
@@ -122,7 +129,6 @@ class ModToolAdd(ModTool):
print "Warning: Autotools modules are not supported. ",
print "Files will be created, but Makefiles will not be edited."
self._skip_cmakefiles = True
- self._license_file = options.license_file
def setup_choose_license(self):
""" Select a license by the following rules, in this order:
@@ -140,7 +146,7 @@ class ModToolAdd(ModTool):
elif self._info['is_component']:
return Templates['grlicense']
else:
- return Templates['defaultlicense']
+ return get_template('defaultlicense', **self._info)
def _write_tpl(self, tpl, path, fname):
""" Shorthand for writing a substituted template to a file"""
diff --git a/gr-utils/python/modtool/templates.py b/gr-utils/python/modtool/templates.py
index dc840df392..9caf658194 100644
--- a/gr-utils/python/modtool/templates.py
+++ b/gr-utils/python/modtool/templates.py
@@ -26,7 +26,7 @@ Templates = {}
# Default licence
Templates['defaultlicense'] = '''
-Copyright %d <+YOU OR YOUR COMPANY+>.
+Copyright %d ${copyrightholder}.
This is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index 859b9e9045..4c782a7f7d 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -96,8 +96,10 @@ install(
COMPONENT "grc"
)
+file(GLOB py_files "*.py")
+
GR_PYTHON_INSTALL(
- FILES __init__.py
+ FILES ${py_files}
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc
COMPONENT "grc"
)
@@ -133,13 +135,9 @@ endif(WIN32)
########################################################################
# Add subdirectories
########################################################################
-add_subdirectory(base)
add_subdirectory(blocks)
-add_subdirectory(freedesktop)
-add_subdirectory(grc_gnuradio)
add_subdirectory(gui)
-add_subdirectory(python)
+add_subdirectory(core)
add_subdirectory(scripts)
-add_subdirectory(examples)
endif(ENABLE_GRC)
diff --git a/grc/__main__.py b/grc/__main__.py
new file mode 100644
index 0000000000..899d0195d1
--- /dev/null
+++ b/grc/__main__.py
@@ -0,0 +1,20 @@
+# Copyright 2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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
+
+from .main import main
+
+main()
diff --git a/grc/base/Block.py b/grc/base/Block.py
deleted file mode 100644
index 77c3145173..0000000000
--- a/grc/base/Block.py
+++ /dev/null
@@ -1,542 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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
-"""
-
-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
-
-
-class TemplateArg(UserDict):
- """
- A cheetah template argument created from a param.
- The str of this class evaluates to the param's to code method.
- The use of this class as a dictionary (enum only) will reveal the enum opts.
- The __call__ or () method can return the param evaluated to a raw python data type.
- """
-
- def __init__(self, param):
- UserDict.__init__(self)
- self._param = param
- if param.is_enum():
- for key in param.get_opt_keys():
- self[key] = str(param.get_opt(key))
-
- def __str__(self):
- return str(self._param.to_code())
-
- def __call__(self):
- return self._param.get_evaluated()
-
-
-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):
- """
- Make a new block from nested data.
-
- Args:
- flow: graph the parent element
- n: the nested odict
-
- Returns:
- block a new block
- """
- #build the block
- Element.__init__(self, flow_graph)
- #grab the data
- params = n.findall('param')
- sources = n.findall('source')
- sinks = n.findall('sink')
- 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')
- self._bussify_source = n.find('bus_source')
- self._var_value = n.find('var_value') or '$value'
-
- # get list of param tabs
- n_tabs = n.find('param_tab_order') or None
- self._param_tab_labels = n_tabs.findall('tab') if n_tabs is not None else [DEFAULT_PARAM_TAB]
-
- #create the param objects
- self._params = list()
- #add the id param
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({
- 'name': 'ID',
- 'key': 'id',
- 'type': 'id',
- })
- ))
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({
- 'name': 'Enabled',
- 'key': '_enabled',
- 'type': 'raw',
- 'value': 'True',
- 'hide': 'all',
- })
- ))
- for param in imap(lambda n: self.get_parent().get_parent().Param(block=self, n=n), params):
- key = param.get_key()
- #test against repeated keys
- if key in self.get_param_keys():
- raise Exception, 'Key "%s" already exists in params'%key
- #store the param
- self.get_params().append(param)
- #create the source objects
- self._sources = list()
- for source in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='source'), sources):
- key = source.get_key()
- #test against repeated keys
- if key in self.get_source_keys():
- raise Exception, 'Key "%s" already exists in sources'%key
- #store the port
- self.get_sources().append(source)
- self.back_ofthe_bus(self.get_sources())
- #create the sink objects
- self._sinks = list()
- for sink in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='sink'), sinks):
- key = sink.get_key()
- #test against repeated keys
- if key in self.get_sink_keys():
- raise Exception, 'Key "%s" already exists in sinks'%key
- #store the port
- self.get_sinks().append(sink)
- self.back_ofthe_bus(self.get_sinks())
- self.current_bus_structure = {'source':'','sink':''};
-
- # Virtual source/sink and pad source/sink blocks are
- # indistinguishable from normal GR blocks. Make explicit
- # checks for them here since they have no work function or
- # buffers to manage.
- is_virtual_or_pad = self._key in (
- "virtual_source", "virtual_sink", "pad_source", "pad_sink")
- is_variable = self._key.startswith('variable')
-
- # Disable blocks that are virtual/pads or variables
- if is_virtual_or_pad or is_variable:
- self._flags += BLOCK_FLAG_DISABLE_BYPASS
-
- if not (is_virtual_or_pad or is_variable or self._key == 'options'):
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Block Alias',
- 'key': 'alias',
- 'type': 'string',
- 'hide': 'part',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
-
- if (len(sources) or len(sinks)) and not is_virtual_or_pad:
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Core Affinity',
- 'key': 'affinity',
- 'type': 'int_vector',
- 'hide': 'part',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
- if len(sources) and not is_virtual_or_pad:
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Min Output Buffer',
- 'key': 'minoutbuf',
- 'type': 'int',
- 'hide': 'part',
- 'value': '0',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Max Output Buffer',
- 'key': 'maxoutbuf',
- 'type': 'int',
- 'hide': 'part',
- 'value': '0',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
-
- self.get_params().append(self.get_parent().get_parent().Param(
- block=self,
- n=odict({'name': 'Comment',
- 'key': 'comment',
- 'type': '_multiline',
- 'hide': 'part',
- 'value': '',
- 'tab': ADVANCED_PARAM_TAB
- })
- ))
-
- def back_ofthe_bus(self, portlist):
- portlist.sort(key=lambda p: p._type == 'bus')
-
- def filter_bus_port(self, ports):
- 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.
-
- Returns:
- true for enabled
- """
- return not (self.get_state() == BLOCK_DISABLED)
-
- def set_enabled(self, enabled):
- """
- Set the enabled state of the block.
-
- 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
- """
- 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())
-
- def get_id(self): return self.get_param('id').get_value()
- def is_block(self): return True
- def get_name(self): return self._name
- def get_key(self): return self._key
- def get_category(self): return self._category
- def set_category(self, cat): self._category = cat
- def get_doc(self): return ''
- def get_ports(self): return self.get_sources() + self.get_sinks()
- def get_ports_gui(self): return self.filter_bus_port(self.get_sources()) + self.filter_bus_port(self.get_sinks());
- def get_children(self): return self.get_ports() + self.get_params()
- def get_children_gui(self): return self.get_ports_gui() + self.get_params()
- 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
- ##############################################
- def get_param_tab_labels(self): return self._param_tab_labels
- def get_param_keys(self): return _get_keys(self._params)
- def get_param(self, key): return _get_elem(self._params, key)
- def get_params(self): return self._params
- def has_param(self, key):
- try:
- _get_elem(self._params, key);
- return True;
- except:
- return False;
-
- ##############################################
- # Access Sinks
- ##############################################
- def get_sink_keys(self): return _get_keys(self._sinks)
- def get_sink(self, key): return _get_elem(self._sinks, key)
- def get_sinks(self): return self._sinks
- def get_sinks_gui(self): return self.filter_bus_port(self.get_sinks())
-
- ##############################################
- # Access Sources
- ##############################################
- def get_source_keys(self): return _get_keys(self._sources)
- def get_source(self, key): return _get_elem(self._sources, key)
- def get_sources(self): return self._sources
- def get_sources_gui(self): return self.filter_bus_port(self.get_sources());
-
- def get_connections(self):
- return sum([port.get_connections() for port in self.get_ports()], [])
-
- def resolve_dependencies(self, tmpl):
- """
- Resolve a paramater dependency with cheetah templates.
-
- Args:
- tmpl: the string with dependencies
-
- Returns:
- the resolved value
- """
- tmpl = str(tmpl)
- if '$' not in tmpl: return tmpl
- n = dict((p.get_key(), TemplateArg(p)) for p in self.get_params())
- try:
- return str(Template(tmpl, n))
- except Exception as err:
- return "Template error: %s\n %s" % (tmpl, err)
-
- ##############################################
- # Controller Modify
- ##############################################
- def type_controller_modify(self, direction):
- """
- Change the type controller.
-
- Args:
- direction: +1 or -1
-
- Returns:
- true for change
- """
- changed = False
- type_param = None
- for param in filter(lambda p: p.is_enum(), self.get_params()):
- children = self.get_ports() + self.get_params()
- #priority to the type controller
- if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param
- #use param if type param is unset
- if not type_param: type_param = param
- if type_param:
- #try to increment the enum by direction
- try:
- keys = type_param.get_option_keys()
- old_index = keys.index(type_param.get_value())
- new_index = (old_index + direction + len(keys))%len(keys)
- type_param.set_value(keys[new_index])
- changed = True
- except: pass
- return changed
-
- def port_controller_modify(self, direction):
- """
- Change the port controller.
-
- Args:
- direction: +1 or -1
-
- Returns:
- true for change
- """
- return False
-
- def form_bus_structure(self, direc):
- if direc == 'source':
- get_p = self.get_sources;
- get_p_gui = self.get_sources_gui;
- bus_structure = self.get_bus_structure('source');
- else:
- get_p = self.get_sinks;
- get_p_gui = self.get_sinks_gui
- bus_structure = self.get_bus_structure('sink');
-
- struct = [range(len(get_p()))];
- if True in map(lambda a: isinstance(a.get_nports(), int), get_p()):
-
-
- structlet = [];
- last = 0;
- for j in [i.get_nports() for i in get_p() if isinstance(i.get_nports(), int)]:
- structlet.extend(map(lambda a: a+last, range(j)));
- last = structlet[-1] + 1;
- struct = [structlet];
- if bus_structure:
-
- struct = bus_structure
-
- self.current_bus_structure[direc] = struct;
- return struct
-
- def bussify(self, n, direc):
- if direc == 'source':
- get_p = self.get_sources;
- get_p_gui = self.get_sources_gui;
- bus_structure = self.get_bus_structure('source');
- else:
- get_p = self.get_sinks;
- get_p_gui = self.get_sinks_gui
- bus_structure = self.get_bus_structure('sink');
-
-
- for elt in get_p():
- for connect in elt.get_connections():
- self.get_parent().remove_element(connect);
-
-
-
-
-
-
- if (not 'bus' in map(lambda a: a.get_type(), get_p())) and len(get_p()) > 0:
-
- struct = self.form_bus_structure(direc);
- self.current_bus_structure[direc] = struct;
- if get_p()[0].get_nports():
- n['nports'] = str(1);
-
- for i in range(len(struct)):
- n['key'] = str(len(get_p()));
- n = odict(n);
- port = self.get_parent().get_parent().Port(block=self, n=n, dir=direc);
- get_p().append(port);
-
-
-
-
- elif 'bus' in map(lambda a: a.get_type(), get_p()):
- for elt in get_p_gui():
- get_p().remove(elt);
- self.current_bus_structure[direc] = ''
- ##############################################
- ## Import/Export Methods
- ##############################################
- def export_data(self):
- """
- Export this block's params to nested data.
-
- Returns:
- a nested data odict
- """
- n = odict()
- n['key'] = self.get_key()
- 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()):
- n['bus_source'] = str(1);
- return n
-
- def import_data(self, n):
- """
- Import this block's params from nested data.
- Any param keys that do not exist will be ignored.
- Since params can be dynamically created based another param,
- call rewrite, and repeat the load until the params stick.
- This call to rewrite will also create any dynamic ports
- that are needed for the connections creation phase.
-
- Args:
- n: the nested data odict
- """
- get_hash = lambda: hash(tuple(map(hash, self.get_params())))
- my_hash = 0
- while get_hash() != my_hash:
- params_n = n.findall('param')
- for param_n in params_n:
- key = param_n.find('key')
- value = param_n.find('value')
- #the key must exist in this block's params
- if key in self.get_param_keys():
- self.get_param(key).set_value(value)
- #store hash and call rewrite
- my_hash = get_hash()
- self.rewrite()
- bussinks = n.findall('bus_sink');
- if len(bussinks) > 0 and not self._bussify_sink:
- self.bussify({'name':'bus','type':'bus'}, 'sink')
- elif len(bussinks) > 0:
- self.bussify({'name':'bus','type':'bus'}, 'sink')
- self.bussify({'name':'bus','type':'bus'}, 'sink')
- bussrcs = n.findall('bus_source');
- if len(bussrcs) > 0 and not self._bussify_source:
- self.bussify({'name':'bus','type':'bus'}, 'source')
- elif len(bussrcs) > 0:
- self.bussify({'name':'bus','type':'bus'}, 'source')
- self.bussify({'name':'bus','type':'bus'}, 'source')
diff --git a/grc/base/Constants.py b/grc/base/Constants.py
deleted file mode 100644
index 1e83de63b5..0000000000
--- a/grc/base/Constants.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""
-Copyright 2008, 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 os
-
-#data files
-DATA_DIR = os.path.dirname(__file__)
-FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd')
-BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd')
-
-# file format versions:
-# 0: undefined / legacy
-# 1: non-numeric message port keys (label is used instead)
-FLOW_GRAPH_FILE_FORMAT_VERSION = 1
-
-# Param tabs
-DEFAULT_PARAM_TAB = "General"
-ADVANCED_PARAM_TAB = "Advanced"
-
-# Port domains
-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_FLAG_NEED_QT_GUI = 'need_qt_gui'
-BLOCK_FLAG_NEED_WX_GUI = 'need_ex_gui'
-
-# Block States
-BLOCK_DISABLED = 0
-BLOCK_ENABLED = 1
-BLOCK_BYPASSED = 2
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
deleted file mode 100644
index 0398dfd011..0000000000
--- a/grc/base/FlowGraph.py
+++ /dev/null
@@ -1,484 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 time
-from operator import methodcaller
-from itertools import ifilter
-
-from .. gui import Messages
-
-from . import odict
-from .Element import Element
-from .Constants import FLOW_GRAPH_FILE_FORMAT_VERSION
-
-
-class FlowGraph(Element):
-
- def __init__(self, platform):
- """
- Make a flow graph from the arguments.
-
- Args:
- platform: a platforms with blocks and contrcutors
-
- Returns:
- the flow graph object
- """
- #initialize
- Element.__init__(self, platform)
- self._elements = []
- self._timestamp = time.ctime()
- #inital blank import
- self.import_data()
-
- def _get_unique_id(self, base_id=''):
- """
- Get a unique id starting with the base id.
-
- Args:
- base_id: the id starts with this and appends a count
-
- Returns:
- a unique id
- """
- index = 0
- while True:
- id = '%s_%d' % (base_id, index)
- index += 1
- #make sure that the id is not used by another block
- if not filter(lambda b: b.get_id() == id, self.get_blocks()): return id
-
- def __str__(self):
- return 'FlowGraph - %s(%s)' % (self.get_option('title'), self.get_option('id'))
-
- def get_complexity(self):
- """
- Determines the complexity of a flowgraph
- """
- dbal = 0
- block_list = self.get_blocks()
- for block in block_list:
- # Skip options block
- if block.get_key() == 'options':
- continue
-
- # Don't worry about optional sinks?
- sink_list = filter(lambda c: not c.get_optional(), block.get_sinks())
- source_list = filter(lambda c: not c.get_optional(), block.get_sources())
- sinks = float(len(sink_list))
- sources = float(len(source_list))
- base = max(min(sinks, sources), 1)
-
- # Port ratio multiplier
- if min(sinks, sources) > 0:
- multi = sinks / sources
- multi = (1 / multi) if multi > 1 else multi
- else:
- multi = 1
-
- # Connection ratio multiplier
- sink_multi = max(float(sum(map(lambda c: len(c.get_connections()), sink_list)) / max(sinks, 1.0)), 1.0)
- source_multi = max(float(sum(map(lambda c: len(c.get_connections()), source_list)) / max(sources, 1.0)), 1.0)
- dbal = dbal + (base * multi * sink_multi * source_multi)
-
- elements = float(len(self.get_elements()))
- connections = float(len(self.get_connections()))
- disabled_connections = len(filter(lambda c: not c.get_enabled(), self.get_connections()))
- blocks = float(len(block_list))
- variables = elements - blocks - connections
- enabled = float(len(self.get_enabled_blocks()))
-
- # Disabled multiplier
- if enabled > 0:
- disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 1)), 0.05))
- else:
- disabled_multi = 1
-
- # Connection multiplier (How many connections )
- if (connections - disabled_connections) > 0:
- conn_multi = 1 / (max(1 - (disabled_connections / max(connections, 1)), 0.05))
- else:
- conn_multi = 1
-
- final = round(max((dbal - 1) * disabled_multi * conn_multi * connections, 0.0) / 1000000, 6)
- return final
-
- def rewrite(self):
- def refactor_bus_structure():
-
- for block in self.get_blocks():
- for direc in ['source', 'sink']:
- if direc == 'source':
- get_p = block.get_sources;
- get_p_gui = block.get_sources_gui;
- bus_structure = block.form_bus_structure('source');
- else:
- get_p = block.get_sinks;
- get_p_gui = block.get_sinks_gui
- 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:
- for connect in get_p_gui()[-1].get_connections():
- block.get_parent().remove_element(connect);
- get_p().remove(get_p_gui()[-1]);
- elif len(get_p_gui()) < len(bus_structure):
- n = {'name':'bus','type':'bus'};
- if True in map(lambda a: isinstance(a.get_nports(), int), get_p()):
- n['nports'] = str(1);
-
- times = range(len(get_p_gui()), len(bus_structure));
-
- for i in times:
- n['key'] = str(len(get_p()));
- n = odict(n);
- 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()
-
- def get_option(self, key):
- """
- Get the option for a given key.
- The option comes from the special options block.
-
- Args:
- key: the param key for the options block
-
- Returns:
- the value held by that param
- """
- return self._options_block.get_param(key).get_evaluated()
-
- def is_flow_graph(self): return True
-
- ##############################################
- ## Access Elements
- ##############################################
- def get_block(self, id):
- for block in self.iter_blocks():
- if block.get_id() == id:
- return block
- raise KeyError('No block with ID {0!r}'.format(id))
-
- def iter_blocks(self):
- return ifilter(methodcaller('is_block'), self.get_elements())
-
- def get_blocks(self):
- return list(self.iter_blocks())
-
- def iter_connections(self):
- return ifilter(methodcaller('is_connection'), self.get_elements())
-
- def get_connections(self):
- return list(self.iter_connections())
-
- def get_elements(self):
- """
- Get a list of all the elements.
- Always ensure that the options block is in the list (only once).
-
- Returns:
- the element list
- """
- options_block_count = self._elements.count(self._options_block)
- if not options_block_count:
- self._elements.append(self._options_block)
- for i in range(options_block_count-1):
- self._elements.remove(self._options_block)
- return self._elements
-
- get_children = get_elements
-
- def iter_enabled_blocks(self):
- """
- Get an iterator of all blocks that are enabled and not bypassed.
- """
- return ifilter(methodcaller('get_enabled'), self.iter_blocks())
-
- def get_enabled_blocks(self):
- """
- Get a list of all blocks that are enabled and not bypassed.
-
- Returns:
- a list of blocks
- """
- return list(self.iter_enabled_blocks())
-
- def get_bypassed_blocks(self):
- """
- Get a list of all blocks that are bypassed.
-
- Returns:
- a list of blocks
- """
- return filter(methodcaller('get_bypassed'), self.iter_blocks())
-
- def get_enabled_connections(self):
- """
- Get a list of all connections that are enabled.
-
- Returns:
- a list of connections
- """
- return filter(methodcaller('get_enabled'), self.get_connections())
-
- def get_new_block(self, key):
- """
- Get a new block of the specified key.
- Add the block to the list of elements.
-
- Args:
- key: the block key
-
- Returns:
- the new block or None if not found
- """
- if key not in self.get_parent().get_block_keys(): return None
- block = self.get_parent().get_new_block(self, key)
- self.get_elements().append(block);
- if block._bussify_sink:
- block.bussify({'name':'bus','type':'bus'}, 'sink')
- if block._bussify_source:
- block.bussify({'name':'bus','type':'bus'}, 'source')
- return block;
-
- def connect(self, porta, portb):
- """
- Create a connection between porta and portb.
-
- Args:
- porta: a port
- portb: another port
- @throw Exception bad connection
-
- Returns:
- the new connection
- """
- connection = self.get_parent().Connection(flow_graph=self, porta=porta, portb=portb)
- self.get_elements().append(connection)
- return connection
-
- def remove_element(self, element):
- """
- Remove the element from the list of elements.
- If the element is a port, remove the whole block.
- If the element is a block, remove its connections.
- If the element is a connection, just remove the connection.
- """
- if element not in self.get_elements(): return
- #found a port, set to parent signal block
- if element.is_port():
- element = element.get_parent()
- #remove block, remove all involved connections
- if element.is_block():
- for port in element.get_ports():
- map(self.remove_element, port.get_connections())
- if element.is_connection():
- if element.is_bus():
- cons_list = []
- for i in map(lambda a: a.get_connections(), element.get_source().get_associated_ports()):
- cons_list.extend(i);
- map(self.remove_element, cons_list);
- self.get_elements().remove(element)
-
- def evaluate(self, expr):
- """
- Evaluate the expression.
-
- Args:
- expr: the string expression
- @throw NotImplementedError
- """
- raise NotImplementedError
-
- ##############################################
- ## Import/Export Methods
- ##############################################
- def export_data(self):
- """
- Export this flow graph to nested data.
- Export all block and connection data.
-
- Returns:
- a nested data odict
- """
- # sort blocks and connections for nicer diffs
- blocks = sorted(self.iter_blocks(), key=lambda b: (
- b.get_key() != 'options', # options to the front
- not b.get_key().startswith('variable'), # then vars
- str(b)
- ))
- connections = sorted(self.get_connections(), key=str)
- n = odict()
- n['timestamp'] = self._timestamp
- n['block'] = [b.export_data() for b in blocks]
- n['connection'] = [c.export_data() for c in connections]
- instructions = odict({
- 'created': self.get_parent().get_version_short(),
- 'format': FLOW_GRAPH_FILE_FORMAT_VERSION,
- })
- return odict({'flow_graph': n, '_instructions': instructions})
-
- def import_data(self, n=None):
- """
- Import blocks and connections into this flow graph.
- Clear this flowgraph of all previous blocks and connections.
- Any blocks or connections in error will be ignored.
-
- Args:
- n: the nested data odict
- """
- errors = False
- self._elements = list() # remove previous elements
- # set file format
- try:
- instructions = n.find('_instructions') or {}
- file_format = int(instructions.get('format', '0')) or _guess_file_format_1(n)
- except:
- file_format = 0
-
- fg_n = n and n.find('flow_graph') or odict() # use blank data if none provided
- self._timestamp = fg_n.find('timestamp') or time.ctime()
-
- # build the blocks
- self._options_block = self.get_parent().get_new_block(self, 'options')
- for block_n in fg_n.findall('block'):
- key = block_n.find('key')
- block = self._options_block if key == 'options' else self.get_new_block(key)
-
- if not block: # looks like this block key cannot be found
- # create a dummy block instead
- block = self.get_new_block('dummy_block')
- # Ugly ugly ugly
- _initialize_dummy_block(block, block_n)
- Messages.send_error_msg_load('Block key "%s" not found' % key)
-
- block.import_data(block_n)
-
- self.rewrite() # evaluate stuff like nports before adding connections
-
- # build the connections
- def verify_and_get_port(key, block, dir):
- ports = block.get_sinks() if dir == 'sink' else block.get_sources()
- for port in ports:
- if key == port.get_key():
- break
- if not key.isdigit() and port.get_type() == '' and key == port.get_name():
- break
- else:
- if block.is_dummy_block():
- port = _dummy_block_add_port(block, key, dir)
- else:
- raise LookupError('%s key %r not in %s block keys' % (dir, key, dir))
- return port
-
- for connection_n in fg_n.findall('connection'):
- # get the block ids and port keys
- source_block_id = connection_n.find('source_block_id')
- sink_block_id = connection_n.find('sink_block_id')
- source_key = connection_n.find('source_key')
- sink_key = connection_n.find('sink_key')
- try:
- source_block = self.get_block(source_block_id)
- sink_block = self.get_block(sink_block_id)
-
- # fix old, numeric message ports keys
- if file_format < 1:
- source_key, sink_key = _update_old_message_port_keys(
- source_key, sink_key, source_block, sink_block)
-
- # build the connection
- source_port = verify_and_get_port(source_key, source_block, 'source')
- sink_port = verify_and_get_port(sink_key, sink_block, 'sink')
- self.connect(source_port, sink_port)
- except LookupError as e:
- Messages.send_error_load(
- 'Connection between %s(%s) and %s(%s) could not be made.\n\t%s' % (
- source_block_id, source_key, sink_block_id, sink_key, e))
- errors = True
-
- self.rewrite() # global rewrite
- return errors
-
-
-def _update_old_message_port_keys(source_key, sink_key, source_block, sink_block):
- """Backward compatibility for message port keys
-
- Message ports use their names as key (like in the 'connect' method).
- Flowgraph files from former versions still have numeric keys stored for
- message connections. These have to be replaced by the name of the
- respective port. The correct message port is deduced from the integer
- value of the key (assuming the order has not changed).
-
- The connection ends are updated only if both ends translate into a
- message port.
- """
- try:
- # get ports using the "old way" (assuming liner indexed keys)
- source_port = source_block.get_sources()[int(source_key)]
- sink_port = sink_block.get_sinks()[int(sink_key)]
- if source_port.get_type() == "message" and sink_port.get_type() == "message":
- source_key, sink_key = source_port.get_key(), sink_port.get_key()
- except (ValueError, IndexError):
- pass
- return source_key, sink_key # do nothing
-
-
-def _guess_file_format_1(n):
- """Try to guess the file format for flow-graph files without version tag"""
- try:
- has_non_numeric_message_keys = any(not (
- connection_n.find('source_key').isdigit() and
- connection_n.find('sink_key').isdigit()
- ) for connection_n in n.find('flow_graph').findall('connection'))
- if has_non_numeric_message_keys:
- return 1
- except:
- pass
- return 0
-
-
-def _initialize_dummy_block(block, block_n):
- """This is so ugly... dummy-fy a block
-
- Modify block object to get the behaviour for a missing block
- """
- block._key = block_n.find('key')
- block.is_dummy_block = lambda: True
- block.is_valid = lambda: False
- block.get_enabled = lambda: False
- for param_n in block_n.findall('param'):
- if param_n['key'] not in block.get_param_keys():
- new_param_n = odict({'key': param_n['key'], 'name': param_n['key'], 'type': 'string'})
- block.get_params().append(block.get_parent().get_parent().Param(block=block, n=new_param_n))
-
-
-def _dummy_block_add_port(block, key, dir):
- """This is so ugly... Add a port to a dummy-field block"""
- port_n = odict({'name': '?', 'key': key, 'type': ''})
- port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
- if port.is_source():
- block.get_sources().append(port)
- else:
- block.get_sinks().append(port)
- return port
diff --git a/grc/base/Param.py b/grc/base/Param.py
deleted file mode 100644
index 34dd36e790..0000000000
--- a/grc/base/Param.py
+++ /dev/null
@@ -1,205 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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
-"""
-
-from . import odict
-from Element import Element
-
-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 Option(Element):
-
- def __init__(self, param, n):
- Element.__init__(self, param)
- self._name = n.find('name')
- self._key = n.find('key')
- self._opts = dict()
- opts = n.findall('opt')
- #test against opts when non enum
- if not self.get_parent().is_enum() and opts:
- raise Exception, 'Options for non-enum types cannot have sub-options'
- #extract opts
- for opt in opts:
- #separate the key:value
- try: key, value = opt.split(':')
- except: raise Exception, 'Error separating "%s" into key:value'%opt
- #test against repeated keys
- if self._opts.has_key(key):
- raise Exception, 'Key "%s" already exists in option'%key
- #store the option
- self._opts[key] = value
-
- def __str__(self): return 'Option %s(%s)'%(self.get_name(), self.get_key())
- def get_name(self): return self._name
- def get_key(self): return self._key
-
- ##############################################
- # Access Opts
- ##############################################
- def get_opt_keys(self): return self._opts.keys()
- def get_opt(self, key): return self._opts[key]
- def get_opts(self): return self._opts.values()
-
-class Param(Element):
-
- def __init__(self, block, n):
- """
- Make a new param from nested data.
-
- Args:
- block: the parent element
- n: the nested odict
- """
- # if the base key is a valid param key, copy its data and overlay this params data
- base_key = n.find('base_key')
- if base_key and base_key in block.get_param_keys():
- n_expanded = block.get_param(base_key)._n.copy()
- n_expanded.update(n)
- n = n_expanded
- # save odict in case this param will be base for another
- self._n = n
- # parse the data
- self._name = n.find('name')
- self._key = n.find('key')
- value = n.find('value') or ''
- self._type = n.find('type') or 'raw'
- self._hide = n.find('hide') or ''
- self._tab_label = n.find('tab') or block.get_param_tab_labels()[0]
- if not self._tab_label in block.get_param_tab_labels():
- block.get_param_tab_labels().append(self._tab_label)
- #build the param
- Element.__init__(self, block)
- #create the Option objects from the n data
- self._options = list()
- for option in map(lambda o: Option(param=self, n=o), n.findall('option')):
- key = option.get_key()
- #test against repeated keys
- if key in self.get_option_keys():
- raise Exception, 'Key "%s" already exists in options'%key
- #store the option
- self.get_options().append(option)
- #test the enum options
- if self.is_enum():
- #test against options with identical keys
- if len(set(self.get_option_keys())) != len(self.get_options()):
- raise Exception, 'Options keys "%s" are not unique.'%self.get_option_keys()
- #test against inconsistent keys in options
- opt_keys = self.get_options()[0].get_opt_keys()
- for option in self.get_options():
- if set(opt_keys) != set(option.get_opt_keys()):
- raise Exception, 'Opt keys "%s" are not identical across all options.'%opt_keys
- #if a value is specified, it must be in the options keys
- self._value = value if value or value in self.get_option_keys() else self.get_option_keys()[0]
- if self.get_value() not in self.get_option_keys():
- raise Exception, 'The value "%s" is not in the possible values of "%s".'%(self.get_value(), self.get_option_keys())
- else: self._value = value or ''
- self._default = value
-
- def validate(self):
- """
- Validate the param.
- The value must be evaluated and type must a possible type.
- """
- Element.validate(self)
- if self.get_type() not in self.get_types():
- self.add_error_message('Type "%s" is not a possible type.'%self.get_type())
-
- def get_evaluated(self): raise NotImplementedError
-
- def to_code(self):
- """
- Convert the value to code.
- @throw NotImplementedError
- """
- raise NotImplementedError
-
- def get_types(self):
- """
- Get a list of all possible param types.
- @throw NotImplementedError
- """
- raise NotImplementedError
-
- def get_color(self): return '#FFFFFF'
- def __str__(self): return 'Param - %s(%s)'%(self.get_name(), self.get_key())
- def is_param(self): return True
- def get_name(self): return self.get_parent().resolve_dependencies(self._name).strip()
- def get_key(self): return self._key
- def get_hide(self): return self.get_parent().resolve_dependencies(self._hide).strip()
-
- def get_value(self):
- value = self._value
- if self.is_enum() and value not in self.get_option_keys():
- value = self.get_option_keys()[0]
- self.set_value(value)
- return value
-
- def set_value(self, value): self._value = str(value) #must be a string
-
- def set_default(self, value):
- if self._default == self._value:
- self.set_value(value)
- self._default = str(value)
-
- def get_type(self): return self.get_parent().resolve_dependencies(self._type)
- def get_tab_label(self): return self._tab_label
- def is_enum(self): return self._type == 'enum'
-
- def __repr__(self):
- """
- Get the repr (nice string format) for this param.
- Just return the value (special case enum).
- Derived classes can handle complex formatting.
-
- Returns:
- the string representation
- """
- if self.is_enum(): return self.get_option(self.get_value()).get_name()
- return self.get_value()
-
- ##############################################
- # Access Options
- ##############################################
- def get_option_keys(self): return _get_keys(self.get_options())
- def get_option(self, key): return _get_elem(self.get_options(), key)
- def get_options(self): return self._options
-
- ##############################################
- # Access Opts
- ##############################################
- def get_opt_keys(self): return self.get_option(self.get_value()).get_opt_keys()
- def get_opt(self, key): return self.get_option(self.get_value()).get_opt(key)
- def get_opts(self): return self.get_option(self.get_value()).get_opts()
-
- ##############################################
- ## Import/Export Methods
- ##############################################
- def export_data(self):
- """
- Export this param's key/value.
-
- Returns:
- a nested data odict
- """
- n = odict()
- n['key'] = self.get_key()
- n['value'] = self.get_value()
- return n
diff --git a/grc/base/Platform.py b/grc/base/Platform.py
deleted file mode 100644
index 0cc3fcf1dd..0000000000
--- a/grc/base/Platform.py
+++ /dev/null
@@ -1,271 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 os
-import sys
-from .. base import ParseXML, odict
-from Element import Element as _Element
-from FlowGraph import FlowGraph as _FlowGraph
-from Connection import Connection as _Connection
-from Block import Block as _Block
-from Port import Port as _Port
-from Param import Param as _Param
-from Constants import BLOCK_TREE_DTD, FLOW_GRAPH_DTD, DOMAIN_DTD
-
-
-class Platform(_Element):
- def __init__(self, name, version, key,
- block_paths, block_dtd, default_flow_graph, generator,
- license='', website=None, colors=None):
- """
- Make a platform from the arguments.
-
- Args:
- name: the platform name
- version: the version string
- key: the unique platform key
- block_paths: the file paths to blocks in this platform
- block_dtd: the dtd validator for xml block wrappers
- default_flow_graph: the default flow graph file path
- generator: the generator class for this platform
- colors: a list of title, color_spec tuples
- license: a multi-line license (first line is copyright)
- website: the website url for this platform
-
- Returns:
- a platform object
- """
- _Element.__init__(self)
- self._name = name
- # Save the verion string to the first
- self._version = version[0]
- self._version_major = version[1]
- self._version_api = version[2]
- self._version_minor = version[3]
- self._version_short = version[1] + "." + version[2] + "." + version[3]
-
- self._key = key
- self._license = license
- self._website = website
- self._block_paths = list(set(block_paths))
- self._block_dtd = block_dtd
- self._default_flow_graph = default_flow_graph
- self._generator = generator
- self._colors = colors or []
- #create a dummy flow graph for the blocks
- self._flow_graph = _Element(self)
-
- self._blocks = None
- self._blocks_n = None
- self._category_trees_n = None
- self._domains = dict()
- self._connection_templates = dict()
- self.load_blocks()
-
- def load_blocks(self):
- """load the blocks and block tree from the search paths"""
- # reset
- self._blocks = odict()
- self._blocks_n = odict()
- self._category_trees_n = list()
- self._domains.clear()
- self._connection_templates.clear()
- ParseXML.xml_failures.clear()
- # try to parse and load blocks
- for xml_file in self.iter_xml_files():
- try:
- if xml_file.endswith("block_tree.xml"):
- self.load_category_tree_xml(xml_file)
- elif xml_file.endswith('domain.xml'):
- self.load_domain_xml(xml_file)
- else:
- self.load_block_xml(xml_file)
- except ParseXML.XMLSyntaxError as e:
- # print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s' % (e, xml_file)
- pass
- except Exception as e:
- print >> sys.stderr, 'Warning: XML parsing failed:\n\t%s\n\tIgnoring: %s' % (e, xml_file)
-
- def iter_xml_files(self):
- """Iterator for block descriptions and category trees"""
- get_path = lambda x: os.path.abspath(os.path.expanduser(x))
- for block_path in map(get_path, self._block_paths):
- if os.path.isfile(block_path):
- yield block_path
- elif os.path.isdir(block_path):
- for dirpath, dirnames, filenames in os.walk(block_path):
- for filename in sorted(filter(lambda f: f.endswith('.xml'), filenames)):
- yield os.path.join(dirpath, filename)
-
- def load_block_xml(self, xml_file):
- """Load block description from xml file"""
- # validate and import
- ParseXML.validate_dtd(xml_file, self._block_dtd)
- n = ParseXML.from_file(xml_file).find('block')
- n['block_wrapper_path'] = xml_file # inject block wrapper path
- # get block instance and add it to the list of blocks
- block = self.Block(self._flow_graph, n)
- key = block.get_key()
- if key in self._blocks:
- print >> sys.stderr, 'Warning: Block with key "%s" already exists.\n\tIgnoring: %s' % (key, xml_file)
- else: # store the block
- self._blocks[key] = block
- self._blocks_n[key] = n
- return block
-
- def load_category_tree_xml(self, xml_file):
- """Validate and parse category tree file and add it to list"""
- ParseXML.validate_dtd(xml_file, BLOCK_TREE_DTD)
- n = ParseXML.from_file(xml_file).find('cat')
- self._category_trees_n.append(n)
-
- def load_domain_xml(self, xml_file):
- """Load a domain properties and connection templates from XML"""
- ParseXML.validate_dtd(xml_file, DOMAIN_DTD)
- n = ParseXML.from_file(xml_file).find('domain')
-
- key = n.find('key')
- if not key:
- print >> sys.stderr, 'Warning: Domain with emtpy key.\n\tIgnoring: %s' % xml_file
- return
- if key in self.get_domains(): # test against repeated keys
- print >> sys.stderr, 'Warning: Domain with key "%s" already exists.\n\tIgnoring: %s' % (key, xml_file)
- return
-
- to_bool = lambda s, d: d if s is None else \
- s.lower() not in ('false', 'off', '0', '')
-
- color = n.find('color') or ''
- try:
- import gtk # ugly but handy
- gtk.gdk.color_parse(color)
- except (ValueError, ImportError):
- if color: # no color is okay, default set in GUI
- print >> sys.stderr, 'Warning: Can\'t parse color code "%s" for domain "%s" ' % (color, key)
- color = None
-
- self._domains[key] = dict(
- name=n.find('name') or key,
- multiple_sinks=to_bool(n.find('multiple_sinks'), True),
- multiple_sources=to_bool(n.find('multiple_sources'), False),
- color=color
- )
- for connection_n in n.findall('connection'):
- key = (connection_n.find('source_domain'), connection_n.find('sink_domain'))
- if not all(key):
- print >> sys.stderr, 'Warning: Empty domain key(s) in connection template.\n\t%s' % xml_file
- elif key in self._connection_templates:
- print >> sys.stderr, 'Warning: Connection template "%s" already exists.\n\t%s' % (key, xml_file)
- else:
- self._connection_templates[key] = connection_n.find('make') or ''
-
- def parse_flow_graph(self, flow_graph_file):
- """
- Parse a saved flow graph file.
- Ensure that the file exists, and passes the dtd check.
-
- Args:
- flow_graph_file: the flow graph file
-
- Returns:
- nested data
- @throws exception if the validation fails
- """
- flow_graph_file = flow_graph_file or self._default_flow_graph
- open(flow_graph_file, 'r') # test open
- ParseXML.validate_dtd(flow_graph_file, FLOW_GRAPH_DTD)
- return ParseXML.from_file(flow_graph_file)
-
- def load_block_tree(self, block_tree):
- """
- Load a block tree with categories and blocks.
- Step 1: Load all blocks from the xml specification.
- Step 2: Load blocks with builtin category specifications.
-
- Args:
- block_tree: the block tree object
- """
- #recursive function to load categories and blocks
- def load_category(cat_n, parent=None):
- #add this category
- parent = (parent or []) + [cat_n.find('name')]
- block_tree.add_block(parent)
- #recursive call to load sub categories
- map(lambda c: load_category(c, parent), cat_n.findall('cat'))
- #add blocks in this category
- for block_key in cat_n.findall('block'):
- if block_key not in self.get_block_keys():
- print >> sys.stderr, 'Warning: Block key "%s" not found when loading category tree.' % (block_key)
- continue
- block = self.get_block(block_key)
- #if it exists, the block's category shall not be overridden by the xml tree
- if not block.get_category():
- block.set_category(parent)
-
- # recursively load the category trees and update the categories for each block
- for category_tree_n in self._category_trees_n:
- load_category(category_tree_n)
-
- #add blocks to block tree
- for block in self.get_blocks():
- #blocks with empty categories are hidden
- if not block.get_category(): continue
- block_tree.add_block(block.get_category(), block)
-
- def __str__(self): return 'Platform - %s(%s)'%(self.get_key(), self.get_name())
-
- def is_platform(self): return True
-
- def get_new_flow_graph(self): return self.FlowGraph(platform=self)
-
- def get_generator(self): return self._generator
-
- ##############################################
- # Access Blocks
- ##############################################
- def get_block_keys(self): return self._blocks.keys()
- def get_block(self, key): return self._blocks[key]
- def get_blocks(self): return self._blocks.values()
- def get_new_block(self, flow_graph, key): return self.Block(flow_graph, n=self._blocks_n[key])
-
- def get_domains(self): return self._domains
- def get_domain(self, key): return self._domains.get(key)
- def get_connection_templates(self): return self._connection_templates
-
- def get_name(self): return self._name
- def get_version(self): return self._version
- def get_version_major(self): return self._version_major
- def get_version_api(self): return self._version_api
- def get_version_minor(self): return self._version_minor
- def get_version_short(self): return self._version_short
-
- def get_key(self): return self._key
- def get_license(self): return self._license
- def get_website(self): return self._website
- def get_colors(self): return self._colors
- def get_block_paths(self): return self._block_paths
-
- ##############################################
- # Constructors
- ##############################################
- FlowGraph = _FlowGraph
- Connection = _Connection
- Block = _Block
- Port = _Port
- Param = _Param
diff --git a/grc/base/Port.py b/grc/base/Port.py
deleted file mode 100644
index d1c35163f5..0000000000
--- a/grc/base/Port.py
+++ /dev/null
@@ -1,136 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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
-"""
-
-from Element import Element
-from . Constants import GR_STREAM_DOMAIN, GR_MESSAGE_DOMAIN
-
-class Port(Element):
-
- def __init__(self, block, n, dir):
- """
- Make a new port from nested data.
-
- Args:
- block: the parent element
- n: the nested odict
- dir: the direction source or sink
- """
- #build the port
- Element.__init__(self, block)
- #grab the data
- self._name = n['name']
- self._key = n['key']
- self._type = n['type'] or ''
- self._domain = n['domain']
- self._hide = n.find('hide') or ''
- self._dir = dir
- self._hide_evaluated = False # updated on rewrite()
-
- def validate(self):
- """
- Validate the port.
- The port must be non-empty and type must a possible type.
- """
- Element.validate(self)
- if self.get_type() not in self.get_types():
- self.add_error_message('Type "%s" is not a possible type.' % self.get_type())
- platform = self.get_parent().get_parent().get_parent()
- if self.get_domain() not in platform.get_domains():
- self.add_error_message('Domain key "%s" is not registered.' % self.get_domain())
-
- def rewrite(self):
- """resolve dependencies in for type and hide"""
- Element.rewrite(self)
- hide = self.get_parent().resolve_dependencies(self._hide).strip().lower()
- self._hide_evaluated = False if hide in ('false', 'off', '0') else bool(hide)
- # update domain if was deduced from (dynamic) port type
- type_ = self.get_type()
- if self._domain == GR_STREAM_DOMAIN and type_ == "message":
- self._domain = GR_MESSAGE_DOMAIN
- self._key = self._name
- if self._domain == GR_MESSAGE_DOMAIN and type_ != "message":
- self._domain = GR_STREAM_DOMAIN
- self._key = '0' # is rectified in rewrite()
-
- def __str__(self):
- if self.is_source():
- return 'Source - %s(%s)'%(self.get_name(), self.get_key())
- if self.is_sink():
- return 'Sink - %s(%s)'%(self.get_name(), self.get_key())
-
- def get_types(self):
- """
- Get a list of all possible port types.
- @throw NotImplementedError
- """
- raise NotImplementedError
-
- def is_port(self): return True
- def get_color(self): return '#FFFFFF'
- def get_name(self):
- number = ''
- if self.get_type() == 'bus':
- busses = filter(lambda a: a._dir == self._dir, self.get_parent().get_ports_gui())
- number = str(busses.index(self)) + '#' + str(len(self.get_associated_ports()))
- return self._name + number
-
- def get_key(self): return self._key
- def is_sink(self): return self._dir == 'sink'
- def is_source(self): return self._dir == 'source'
- def get_type(self): return self.get_parent().resolve_dependencies(self._type)
- def get_domain(self): return self._domain
- def get_hide(self): return self._hide_evaluated
-
- def get_connections(self):
- """
- Get all connections that use this port.
-
- Returns:
- a list of connection objects
- """
- connections = self.get_parent().get_parent().get_connections()
- connections = filter(lambda c: c.get_source() is self or c.get_sink() is self, connections)
- return connections
-
- def get_enabled_connections(self):
- """
- Get all enabled connections that use this port.
-
- Returns:
- a list of connection objects
- """
- return filter(lambda c: c.get_enabled(), self.get_connections())
-
- def get_associated_ports(self):
- if not self.get_type() == 'bus':
- return [self]
- else:
- if self.is_source():
- get_ports = self.get_parent().get_sources
- bus_structure = self.get_parent().current_bus_structure['source']
- else:
- get_ports = self.get_parent().get_sinks
- bus_structure = self.get_parent().current_bus_structure['sink']
-
- ports = [i for i in get_ports() if not i.get_type() == 'bus']
- if bus_structure:
- busses = [i for i in get_ports() if i.get_type() == 'bus']
- bus_index = busses.index(self)
- ports = filter(lambda a: ports.index(a) in bus_structure[bus_index], ports)
- return ports
diff --git a/grc/base/__init__.py b/grc/base/__init__.py
deleted file mode 100644
index 2682db8125..0000000000
--- a/grc/base/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Copyright 2009 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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
-"""
-
-from odict import odict
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index d07c52e9c5..a8775d6872 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -20,23 +20,6 @@
<block>note</block>
<block>import</block>
-
- <block>blks2_selector</block>
- <block>blks2_valve</block>
- <block>blks2_error_rate</block>
-
- <block>xmlrpc_server</block>
- <block>xmlrpc_client</block>
- </cat>
- <cat>
- <name>Networking Tools</name>
- <block>blks2_tcp_source</block>
- <block>blks2_tcp_sink</block>
- </cat>
- <cat>
- <name>Packet Operators</name>
- <block>blks2_packet_decoder</block>
- <block>blks2_packet_encoder</block>
</cat>
<cat>
<name>Variables</name>
diff --git a/grc/checks.py b/grc/checks.py
new file mode 100755
index 0000000000..fd0e5de06a
--- /dev/null
+++ b/grc/checks.py
@@ -0,0 +1,80 @@
+# Copyright 2009-2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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 os
+import warnings
+
+
+GR_IMPORT_ERROR_MESSAGE = """\
+Cannot import gnuradio.
+
+Is the model path environment variable set correctly?
+ All OS: PYTHONPATH
+
+Is the library path environment variable set correctly?
+ Linux: LD_LIBRARY_PATH
+ Windows: PATH
+ MacOSX: DYLD_LIBRARY_PATH
+"""
+
+
+def die(error, message):
+ msg = "{0}\n\n({1})".format(message, error)
+ try:
+ import gtk
+ d = gtk.MessageDialog(
+ type=gtk.MESSAGE_ERROR,
+ buttons=gtk.BUTTONS_CLOSE,
+ message_format=msg,
+ )
+ d.set_title(type(error).__name__)
+ d.run()
+ exit(1)
+ except ImportError:
+ exit(type(error).__name__ + '\n\n' + msg)
+
+
+def check_gtk():
+ try:
+ warnings.filterwarnings("error")
+ import pygtk
+ pygtk.require('2.0')
+ import gtk
+ gtk.init_check()
+ warnings.filterwarnings("always")
+ except Exception as err:
+ die(err, "Failed to initialize GTK. If you are running over ssh, "
+ "did you enable X forwarding and start ssh with -X?")
+
+
+def check_gnuradio_import():
+ try:
+ from gnuradio import gr
+ except ImportError as err:
+ die(err, GR_IMPORT_ERROR_MESSAGE)
+
+
+def check_blocks_path():
+ if 'GR_DONT_LOAD_PREFS' in os.environ and not os.environ.get('GRC_BLOCKS_PATH', ''):
+ die(EnvironmentError("No block definitions available"),
+ "Can't find block definitions. Use config.conf or GRC_BLOCKS_PATH.")
+
+
+def do_all():
+ check_gnuradio_import()
+ check_gtk()
+ check_blocks_path()
diff --git a/grc/core/Block.py b/grc/core/Block.py
new file mode 100644
index 0000000000..cb4eb0db61
--- /dev/null
+++ b/grc/core/Block.py
@@ -0,0 +1,846 @@
+"""
+Copyright 2008-2015 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 collections
+import itertools
+
+from Cheetah.Template import Template
+
+from .utils import epy_block_io, odict
+from . Constants import (
+ BLOCK_FLAG_NEED_QT_GUI, BLOCK_FLAG_NEED_WX_GUI,
+ ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB,
+ BLOCK_FLAG_THROTTLE, BLOCK_FLAG_DISABLE_BYPASS,
+ BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED
+)
+from . Element import Element
+from . FlowGraph import _variable_matcher
+
+
+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 "{}" not found in {}.'.format(key, _get_keys(lst)))
+
+
+class Block(Element):
+
+ is_block = True
+
+ def __init__(self, flow_graph, n):
+ """
+ Make a new block from nested data.
+
+ Args:
+ flow: graph the parent element
+ n: the nested odict
+
+ Returns:
+ block a new block
+ """
+ # Grab the data
+ self._doc = (n.find('doc') or '').strip('\n').replace('\\\n', '')
+ self._imports = map(lambda i: i.strip(), n.findall('import'))
+ self._make = n.find('make')
+ self._var_make = n.find('var_make')
+ self._checks = n.findall('check')
+ self._callbacks = n.findall('callback')
+ self._bus_structure_source = n.find('bus_structure_source') or ''
+ self._bus_structure_sink = n.find('bus_structure_sink') or ''
+ self.port_counters = [itertools.count(), itertools.count()]
+
+ # Build the block
+ Element.__init__(self, flow_graph)
+
+ # Grab the data
+ params = n.findall('param')
+ sources = n.findall('source')
+ sinks = n.findall('sink')
+ 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')
+ self._bussify_source = n.find('bus_source')
+ self._var_value = n.find('var_value') or '$value'
+
+ # Get list of param tabs
+ n_tabs = n.find('param_tab_order') or None
+ self._param_tab_labels = n_tabs.findall('tab') if n_tabs is not None else [DEFAULT_PARAM_TAB]
+
+ # Create the param objects
+ self._params = list()
+
+ # Add the id param
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({
+ 'name': 'ID',
+ 'key': 'id',
+ 'type': 'id',
+ })
+ ))
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({
+ 'name': 'Enabled',
+ 'key': '_enabled',
+ 'type': 'raw',
+ 'value': 'True',
+ 'hide': 'all',
+ })
+ ))
+ for param in itertools.imap(lambda n: self.get_parent().get_parent().Param(block=self, n=n), params):
+ key = param.get_key()
+ # Test against repeated keys
+ if key in self.get_param_keys():
+ raise Exception('Key "{}" already exists in params'.format(key))
+ # Store the param
+ self.get_params().append(param)
+ # Create the source objects
+ self._sources = list()
+ for source in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='source'), sources):
+ key = source.get_key()
+ # Test against repeated keys
+ if key in self.get_source_keys():
+ raise Exception('Key "{}" already exists in sources'.format(key))
+ # Store the port
+ self.get_sources().append(source)
+ self.back_ofthe_bus(self.get_sources())
+ # Create the sink objects
+ self._sinks = list()
+ for sink in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='sink'), sinks):
+ key = sink.get_key()
+ # Test against repeated keys
+ if key in self.get_sink_keys():
+ raise Exception('Key "{}" already exists in sinks'.format(key))
+ # Store the port
+ self.get_sinks().append(sink)
+ self.back_ofthe_bus(self.get_sinks())
+ self.current_bus_structure = {'source': '', 'sink': ''}
+
+ # Virtual source/sink and pad source/sink blocks are
+ # indistinguishable from normal GR blocks. Make explicit
+ # checks for them here since they have no work function or
+ # buffers to manage.
+ is_virtual_or_pad = self._key in (
+ "virtual_source", "virtual_sink", "pad_source", "pad_sink")
+ is_variable = self._key.startswith('variable')
+
+ # Disable blocks that are virtual/pads or variables
+ if is_virtual_or_pad or is_variable:
+ self._flags += BLOCK_FLAG_DISABLE_BYPASS
+
+ if not (is_virtual_or_pad or is_variable or self._key == 'options'):
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({'name': 'Block Alias',
+ 'key': 'alias',
+ 'type': 'string',
+ 'hide': 'part',
+ 'tab': ADVANCED_PARAM_TAB
+ })
+ ))
+
+ if (len(sources) or len(sinks)) and not is_virtual_or_pad:
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({'name': 'Core Affinity',
+ 'key': 'affinity',
+ 'type': 'int_vector',
+ 'hide': 'part',
+ 'tab': ADVANCED_PARAM_TAB
+ })
+ ))
+ if len(sources) and not is_virtual_or_pad:
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({'name': 'Min Output Buffer',
+ 'key': 'minoutbuf',
+ 'type': 'int',
+ 'hide': 'part',
+ 'value': '0',
+ 'tab': ADVANCED_PARAM_TAB
+ })
+ ))
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({'name': 'Max Output Buffer',
+ 'key': 'maxoutbuf',
+ 'type': 'int',
+ 'hide': 'part',
+ 'value': '0',
+ 'tab': ADVANCED_PARAM_TAB
+ })
+ ))
+
+ self.get_params().append(self.get_parent().get_parent().Param(
+ block=self,
+ n=odict({'name': 'Comment',
+ 'key': 'comment',
+ 'type': '_multiline',
+ 'hide': 'part',
+ 'value': '',
+ 'tab': ADVANCED_PARAM_TAB
+ })
+ ))
+
+ self._epy_source_hash = -1 # for epy blocks
+ self._epy_reload_error = None
+
+ if self._bussify_sink:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+ if self._bussify_source:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+
+ def get_bus_structure(self, direction):
+ if direction == 'source':
+ bus_structure = self._bus_structure_source
+ else:
+ bus_structure = self._bus_structure_sink
+
+ bus_structure = self.resolve_dependencies(bus_structure)
+
+ if not bus_structure:
+ return '' # TODO: Don't like empty strings. should change this to None eventually
+
+ try:
+ clean_bus_structure = self.get_parent().evaluate(bus_structure)
+ return clean_bus_structure
+ except:
+ return ''
+
+ def validate(self):
+ """
+ Validate this block.
+ Call the base class validate.
+ Evaluate the checks: each check must evaluate to True.
+ """
+ Element.validate(self)
+ # Evaluate the checks
+ for check in self._checks:
+ check_res = self.resolve_dependencies(check)
+ try:
+ if not self.get_parent().evaluate(check_res):
+ self.add_error_message('Check "{}" failed.'.format(check))
+ except:
+ self.add_error_message('Check "{}" did not evaluate.'.format(check))
+
+ # For variables check the value (only if var_value is used
+ if _variable_matcher.match(self.get_key()) and self._var_value != '$value':
+ value = self._var_value
+ try:
+ value = self.get_var_value()
+ self.get_parent().evaluate(value)
+ except Exception as err:
+ self.add_error_message('Value "{}" cannot be evaluated:\n{}'.format(value, err))
+
+ # check if this is a GUI block and matches the selected generate option
+ current_generate_option = self.get_parent().get_option('generate_options')
+
+ def check_generate_mode(label, flag, valid_options):
+ block_requires_mode = (
+ flag in self.get_flags() or
+ self.get_name().upper().startswith(label)
+ )
+ if block_requires_mode and current_generate_option not in valid_options:
+ self.add_error_message("Can't generate this block in mode: {} ".format(
+ repr(current_generate_option)))
+
+ check_generate_mode('WX GUI', BLOCK_FLAG_NEED_WX_GUI, ('wx_gui',))
+ check_generate_mode('QT GUI', BLOCK_FLAG_NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
+ if self._epy_reload_error:
+ self.get_param('_source_code').add_error_message(str(self._epy_reload_error))
+
+ def rewrite(self):
+ """
+ Add and remove ports to adjust for the nports.
+ """
+ Element.rewrite(self)
+ # Check and run any custom rewrite function for this block
+ getattr(self, 'rewrite_' + self._key, lambda: None)()
+
+ # Adjust nports, disconnect hidden ports
+ for ports in (self.get_sources(), self.get_sinks()):
+ for i, master_port in enumerate(ports):
+ nports = master_port.get_nports() or 1
+ num_ports = 1 + len(master_port.get_clones())
+ if master_port.get_hide():
+ for connection in master_port.get_connections():
+ self.get_parent().remove_element(connection)
+ if not nports and num_ports == 1: # Not a master port and no left-over clones
+ continue
+ # Remove excess cloned ports
+ for port in master_port.get_clones()[nports-1:]:
+ # Remove excess connections
+ for connection in port.get_connections():
+ self.get_parent().remove_element(connection)
+ master_port.remove_clone(port)
+ ports.remove(port)
+ # Add more cloned ports
+ for j in range(num_ports, nports):
+ port = master_port.add_clone()
+ ports.insert(ports.index(master_port) + j, port)
+
+ self.back_ofthe_bus(ports)
+ # Renumber non-message/message ports
+ domain_specific_port_index = collections.defaultdict(int)
+ for port in filter(lambda p: p.get_key().isdigit(), ports):
+ domain = port.get_domain()
+ port._key = str(domain_specific_port_index[domain])
+ domain_specific_port_index[domain] += 1
+
+ def port_controller_modify(self, direction):
+ """
+ Change the port controller.
+
+ Args:
+ direction: +1 or -1
+
+ Returns:
+ true for change
+ """
+ changed = False
+ # Concat the nports string from the private nports settings of all ports
+ nports_str = ' '.join([port._nports for port in self.get_ports()])
+ # Modify all params whose keys appear in the nports string
+ for param in self.get_params():
+ if param.is_enum() or param.get_key() not in nports_str:
+ continue
+ # Try to increment the port controller by direction
+ try:
+ value = param.get_evaluated()
+ value = value + direction
+ if 0 < value:
+ param.set_value(value)
+ changed = True
+ except:
+ pass
+ return changed
+
+ def get_doc(self):
+ platform = self.get_parent().get_parent()
+ documentation = platform.block_docstrings.get(self._key, {})
+ from_xml = self._doc.strip()
+ if from_xml:
+ documentation[''] = from_xml
+ return documentation
+
+ def get_imports(self, raw=False):
+ """
+ Resolve all import statements.
+ Split each import statement at newlines.
+ Combine all import statments into a list.
+ Filter empty imports.
+
+ Returns:
+ a list of import statements
+ """
+ if raw:
+ return self._imports
+ return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), []))
+
+ def get_make(self, raw=False):
+ if raw:
+ return self._make
+ return self.resolve_dependencies(self._make)
+
+ def get_var_make(self):
+ return self.resolve_dependencies(self._var_make)
+
+ def get_var_value(self):
+ return self.resolve_dependencies(self._var_value)
+
+ def get_callbacks(self):
+ """
+ Get a list of function callbacks for this block.
+
+ Returns:
+ a list of strings
+ """
+ def make_callback(callback):
+ callback = self.resolve_dependencies(callback)
+ if 'self.' in callback:
+ return callback
+ return 'self.{}.{}'.format(self.get_id(), callback)
+ return map(make_callback, self._callbacks)
+
+ def is_virtual_sink(self):
+ return self.get_key() == 'virtual_sink'
+
+ def is_virtual_source(self):
+ return self.get_key() == 'virtual_source'
+
+ ###########################################################################
+ # Custom rewrite functions
+ ###########################################################################
+
+ def rewrite_epy_block(self):
+ flowgraph = self.get_parent()
+ platform = flowgraph.get_parent()
+ param_blk = self.get_param('_io_cache')
+ param_src = self.get_param('_source_code')
+
+ src = param_src.get_value()
+ src_hash = hash((self.get_id(), src))
+ if src_hash == self._epy_source_hash:
+ return
+
+ try:
+ blk_io = epy_block_io.extract(src)
+
+ except Exception as e:
+ self._epy_reload_error = ValueError(str(e))
+ try: # Load last working block io
+ blk_io = epy_block_io.BlockIO(*eval(param_blk.get_value()))
+ except:
+ return
+ else:
+ self._epy_reload_error = None # Clear previous errors
+ param_blk.set_value(repr(tuple(blk_io)))
+
+ # print "Rewriting embedded python block {!r}".format(self.get_id())
+
+ self._epy_source_hash = src_hash
+ self._name = blk_io.name or blk_io.cls
+ self._doc = blk_io.doc
+ self._imports[0] = 'import ' + self.get_id()
+ self._make = '{0}.{1}({2})'.format(self.get_id(), blk_io.cls, ', '.join(
+ '{0}=${0}'.format(key) for key, _ in blk_io.params))
+
+ params = {}
+ for param in list(self._params):
+ if hasattr(param, '__epy_param__'):
+ params[param.get_key()] = param
+ self._params.remove(param)
+
+ for key, value in blk_io.params:
+ try:
+ param = params[key]
+ param.set_default(value)
+ except KeyError: # need to make a new param
+ name = key.replace('_', ' ').title()
+ n = odict(dict(name=name, key=key, type='raw', value=value))
+ param = platform.Param(block=self, n=n)
+ setattr(param, '__epy_param__', True)
+ self._params.append(param)
+
+ def update_ports(label, ports, port_specs, direction):
+ ports_to_remove = list(ports)
+ iter_ports = iter(ports)
+ ports_new = []
+ port_current = next(iter_ports, None)
+ for key, port_type in port_specs:
+ reuse_port = (
+ port_current is not None and
+ port_current.get_type() == port_type and
+ (key.isdigit() or port_current.get_key() == key)
+ )
+ if reuse_port:
+ ports_to_remove.remove(port_current)
+ port, port_current = port_current, next(iter_ports, None)
+ else:
+ n = odict(dict(name=label + str(key), type=port_type, key=key))
+ if port_type == 'message':
+ n['name'] = key
+ n['optional'] = '1'
+ port = platform.Port(block=self, n=n, dir=direction)
+ ports_new.append(port)
+ # replace old port list with new one
+ del ports[:]
+ ports.extend(ports_new)
+ # remove excess port connections
+ for port in ports_to_remove:
+ for connection in port.get_connections():
+ flowgraph.remove_element(connection)
+
+ update_ports('in', self.get_sinks(), blk_io.sinks, 'sink')
+ update_ports('out', self.get_sources(), blk_io.sources, 'source')
+ self.rewrite()
+
+ def back_ofthe_bus(self, portlist):
+ portlist.sort(key=lambda p: p._type == 'bus')
+
+ def filter_bus_port(self, ports):
+ 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.
+
+ Returns:
+ true for enabled
+ """
+ return not (self.get_state() == BLOCK_DISABLED)
+
+ def set_enabled(self, enabled):
+ """
+ Set the enabled state of the block.
+
+ 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
+ """
+ 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 - {} - {}({})'.format(self.get_id(), self.get_name(), self.get_key())
+
+ def get_id(self):
+ return self.get_param('id').get_value()
+
+ def get_name(self):
+ return self._name
+
+ def get_key(self):
+ return self._key
+
+ def get_category(self):
+ return self._category
+
+ def set_category(self, cat):
+ self._category = cat
+
+ def get_ports(self):
+ return self.get_sources() + self.get_sinks()
+
+ def get_ports_gui(self):
+ return self.filter_bus_port(self.get_sources()) + self.filter_bus_port(self.get_sinks())
+
+ def get_children(self):
+ return self.get_ports() + self.get_params()
+
+ def get_children_gui(self):
+ return self.get_ports_gui() + self.get_params()
+
+ 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
+ ##############################################
+ def get_param_tab_labels(self):
+ return self._param_tab_labels
+
+ def get_param_keys(self):
+ return _get_keys(self._params)
+
+ def get_param(self, key):
+ return _get_elem(self._params, key)
+
+ def get_params(self):
+ return self._params
+
+ def has_param(self, key):
+ try:
+ _get_elem(self._params, key)
+ return True
+ except:
+ return False
+
+ ##############################################
+ # Access Sinks
+ ##############################################
+ def get_sink_keys(self):
+ return _get_keys(self._sinks)
+
+ def get_sink(self, key):
+ return _get_elem(self._sinks, key)
+
+ def get_sinks(self):
+ return self._sinks
+
+ def get_sinks_gui(self):
+ return self.filter_bus_port(self.get_sinks())
+
+ ##############################################
+ # Access Sources
+ ##############################################
+ def get_source_keys(self):
+ return _get_keys(self._sources)
+
+ def get_source(self, key):
+ return _get_elem(self._sources, key)
+
+ def get_sources(self):
+ return self._sources
+
+ def get_sources_gui(self):
+ return self.filter_bus_port(self.get_sources())
+
+ def get_connections(self):
+ return sum([port.get_connections() for port in self.get_ports()], [])
+
+ def resolve_dependencies(self, tmpl):
+ """
+ Resolve a paramater dependency with cheetah templates.
+
+ Args:
+ tmpl: the string with dependencies
+
+ Returns:
+ the resolved value
+ """
+ tmpl = str(tmpl)
+ if '$' not in tmpl:
+ return tmpl
+ n = dict((param.get_key(), param.template_arg)
+ for param in self.get_params()) # TODO: cache that
+ try:
+ return str(Template(tmpl, n))
+ except Exception as err:
+ return "Template error: {}\n {}".format(tmpl, err)
+
+ ##############################################
+ # Controller Modify
+ ##############################################
+ def type_controller_modify(self, direction):
+ """
+ Change the type controller.
+
+ Args:
+ direction: +1 or -1
+
+ Returns:
+ true for change
+ """
+ changed = False
+ type_param = None
+ for param in filter(lambda p: p.is_enum(), self.get_params()):
+ children = self.get_ports() + self.get_params()
+ # Priority to the type controller
+ if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param
+ # Use param if type param is unset
+ if not type_param:
+ type_param = param
+ if type_param:
+ # Try to increment the enum by direction
+ try:
+ keys = type_param.get_option_keys()
+ old_index = keys.index(type_param.get_value())
+ new_index = (old_index + direction + len(keys)) % len(keys)
+ type_param.set_value(keys[new_index])
+ changed = True
+ except:
+ pass
+ return changed
+
+ def form_bus_structure(self, direc):
+ if direc == 'source':
+ get_p = self.get_sources
+ get_p_gui = self.get_sources_gui
+ bus_structure = self.get_bus_structure('source')
+ else:
+ get_p = self.get_sinks
+ get_p_gui = self.get_sinks_gui
+ bus_structure = self.get_bus_structure('sink')
+
+ struct = [range(len(get_p()))]
+ if True in map(lambda a: isinstance(a.get_nports(), int), get_p()):
+ structlet = []
+ last = 0
+ for j in [i.get_nports() for i in get_p() if isinstance(i.get_nports(), int)]:
+ structlet.extend(map(lambda a: a+last, range(j)))
+ last = structlet[-1] + 1
+ struct = [structlet]
+ if bus_structure:
+
+ struct = bus_structure
+
+ self.current_bus_structure[direc] = struct
+ return struct
+
+ def bussify(self, n, direc):
+ if direc == 'source':
+ get_p = self.get_sources
+ get_p_gui = self.get_sources_gui
+ bus_structure = self.get_bus_structure('source')
+ else:
+ get_p = self.get_sinks
+ get_p_gui = self.get_sinks_gui
+ bus_structure = self.get_bus_structure('sink')
+
+ for elt in get_p():
+ for connect in elt.get_connections():
+ self.get_parent().remove_element(connect)
+
+ if ('bus' not in map(lambda a: a.get_type(), get_p())) and len(get_p()) > 0:
+ struct = self.form_bus_structure(direc)
+ self.current_bus_structure[direc] = struct
+ if get_p()[0].get_nports():
+ n['nports'] = str(1)
+
+ for i in range(len(struct)):
+ n['key'] = str(len(get_p()))
+ n = odict(n)
+ port = self.get_parent().get_parent().Port(block=self, n=n, dir=direc)
+ get_p().append(port)
+ elif 'bus' in map(lambda a: a.get_type(), get_p()):
+ for elt in get_p_gui():
+ get_p().remove(elt)
+ self.current_bus_structure[direc] = ''
+
+ ##############################################
+ # Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this block's params to nested data.
+
+ Returns:
+ a nested data odict
+ """
+ n = odict()
+ n['key'] = self.get_key()
+ 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()):
+ n['bus_source'] = str(1)
+ return n
+
+ def get_hash(self):
+ return hash(tuple(map(hash, self.get_params())))
+
+ def import_data(self, n):
+ """
+ Import this block's params from nested data.
+ Any param keys that do not exist will be ignored.
+ Since params can be dynamically created based another param,
+ call rewrite, and repeat the load until the params stick.
+ This call to rewrite will also create any dynamic ports
+ that are needed for the connections creation phase.
+
+ Args:
+ n: the nested data odict
+ """
+ my_hash = 0
+ while self.get_hash() != my_hash:
+ params_n = n.findall('param')
+ for param_n in params_n:
+ key = param_n.find('key')
+ value = param_n.find('value')
+ # The key must exist in this block's params
+ if key in self.get_param_keys():
+ self.get_param(key).set_value(value)
+ # Store hash and call rewrite
+ my_hash = self.get_hash()
+ self.rewrite()
+ bussinks = n.findall('bus_sink')
+ if len(bussinks) > 0 and not self._bussify_sink:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+ elif len(bussinks) > 0:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'sink')
+ bussrcs = n.findall('bus_source')
+ if len(bussrcs) > 0 and not self._bussify_source:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+ elif len(bussrcs) > 0:
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
+ self.bussify({'name': 'bus', 'type': 'bus'}, 'source')
diff --git a/grc/examples/CMakeLists.txt b/grc/core/CMakeLists.txt
index a218dbe500..51b0dacba6 100644
--- a/grc/examples/CMakeLists.txt
+++ b/grc/core/CMakeLists.txt
@@ -17,21 +17,21 @@
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
-# SIMPLE
-install(
- FILES
- simple/variable_config.grc
- DESTINATION ${GR_PKG_DATA_DIR}/examples/grc/simple
+file(GLOB py_files "*.py")
+
+GR_PYTHON_INSTALL(
+ FILES ${py_files}
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core
COMPONENT "grc"
)
-# XMLRPC
+file(GLOB dtd_files "*.dtd")
+
install(
- FILES
- xmlrpc/readme.txt
- xmlrpc/xmlrpc_client.grc
- xmlrpc/xmlrpc_client_script.py
- xmlrpc/xmlrpc_server.grc
- DESTINATION ${GR_PKG_DATA_DIR}/examples/grc/xmlrpc
+ FILES ${dtd_files} default_flow_graph.grc
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core
COMPONENT "grc"
)
+
+add_subdirectory(generator)
+add_subdirectory(utils)
diff --git a/grc/core/Config.py b/grc/core/Config.py
new file mode 100644
index 0000000000..ac38d9978c
--- /dev/null
+++ b/grc/core/Config.py
@@ -0,0 +1,55 @@
+"""
+Copyright 2016 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 os
+from os.path import expanduser, normpath, expandvars, exists
+
+
+class Config(object):
+
+ key = 'grc'
+ name = 'GNU Radio Companion (no gui)'
+ license = __doc__.strip()
+ website = 'http://gnuradio.org'
+
+ hier_block_lib_dir = os.environ.get('GRC_HIER_PATH', expanduser('~/.grc_gnuradio'))
+
+ def __init__(self, prefs_file, version, version_parts=None):
+ self.prefs = prefs_file
+ self.version = version
+ self.version_parts = version_parts or version[1:].split('-', 1)[0].split('.')[:3]
+
+ @property
+ def block_paths(self):
+ path_list_sep = {'/': ':', '\\': ';'}[os.path.sep]
+
+ paths_sources = (
+ self.hier_block_lib_dir,
+ os.environ.get('GRC_BLOCKS_PATH', ''),
+ self.prefs.get_string('grc', 'local_blocks_path', ''),
+ self.prefs.get_string('grc', 'global_blocks_path', ''),
+ )
+
+ collected_paths = sum((paths.split(path_list_sep)
+ for paths in paths_sources), [])
+
+ valid_paths = [normpath(expanduser(expandvars(path)))
+ for path in collected_paths if exists(path)]
+
+ return valid_paths
diff --git a/grc/base/Connection.py b/grc/core/Connection.py
index bf3c75277c..3aa32ef183 100644
--- a/grc/base/Connection.py
+++ b/grc/core/Connection.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008-2011 Free Software Foundation, Inc.
+Copyright 2008-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,11 +17,15 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from Element import Element
-from . import odict
+from . import Constants
+from .Element import Element
+from .utils import odict
+
class Connection(Element):
+ is_connection = True
+
def __init__(self, flow_graph, porta, portb):
"""
Make a new connection given the parent and 2 ports.
@@ -37,72 +41,88 @@ class Connection(Element):
"""
Element.__init__(self, flow_graph)
source = sink = None
- #separate the source and sink
+ # Separate the source and sink
for port in (porta, portb):
- if port.is_source(): source = port
- if port.is_sink(): sink = port
- if not source: raise ValueError('Connection could not isolate source')
- if not sink: raise ValueError('Connection could not isolate sink')
- busses = len(filter(lambda a: a.get_type() == 'bus', [source, sink]))%2
- if not busses == 0: raise ValueError('busses must get with busses')
+ if port.is_source:
+ source = port
+ else:
+ sink = port
+ if not source:
+ raise ValueError('Connection could not isolate source')
+ if not sink:
+ raise ValueError('Connection could not isolate sink')
+ busses = len(filter(lambda a: a.get_type() == 'bus', [source, sink])) % 2
+ if not busses == 0:
+ raise ValueError('busses must get with busses')
if not len(source.get_associated_ports()) == len(sink.get_associated_ports()):
- raise ValueError('port connections must have same cardinality');
- #ensure that this connection (source -> sink) is unique
- for connection in self.get_parent().get_connections():
+ raise ValueError('port connections must have same cardinality')
+ # Ensure that this connection (source -> sink) is unique
+ for connection in flow_graph.connections:
if connection.get_source() is source and connection.get_sink() is sink:
raise LookupError('This connection between source and sink is not unique.')
self._source = source
self._sink = sink
if source.get_type() == 'bus':
- sources = source.get_associated_ports();
- sinks = sink.get_associated_ports();
+ sources = source.get_associated_ports()
+ sinks = sink.get_associated_ports()
for i in range(len(sources)):
try:
- flow_graph.connect(sources[i], sinks[i]);
+ flow_graph.connect(sources[i], sinks[i])
except:
pass
def __str__(self):
- return 'Connection (\n\t%s\n\t\t%s\n\t%s\n\t\t%s\n)'%(
+ return 'Connection (\n\t{}\n\t\t{}\n\t{}\n\t\t{}\n)'.format(
self.get_source().get_parent(),
self.get_source(),
self.get_sink().get_parent(),
self.get_sink(),
)
- def is_connection(self): return True
+ def is_msg(self):
+ return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
+
+ def is_bus(self):
+ return self.get_source().get_type() == self.get_sink().get_type() == 'bus'
def validate(self):
"""
Validate the connections.
+ The ports must match in io size.
+ """
+ """
+ Validate the connections.
The ports must match in type.
"""
Element.validate(self)
platform = self.get_parent().get_parent()
source_domain = self.get_source().get_domain()
sink_domain = self.get_sink().get_domain()
- if (source_domain, sink_domain) not in platform.get_connection_templates():
- self.add_error_message('No connection known for domains "%s", "%s"'
- % (source_domain, sink_domain))
+ if (source_domain, sink_domain) not in platform.connection_templates:
+ self.add_error_message('No connection known for domains "{}", "{}"'.format(
+ source_domain, sink_domain))
too_many_other_sinks = (
- source_domain in platform.get_domains() and
- not platform.get_domain(key=source_domain)['multiple_sinks'] and
+ not platform.domains.get(source_domain, []).get('multiple_sinks', False) and
len(self.get_source().get_enabled_connections()) > 1
)
too_many_other_sources = (
- sink_domain in platform.get_domains() and
- not platform.get_domain(key=sink_domain)['multiple_sources'] and
+ not platform.domains.get(sink_domain, []).get('multiple_sources', False) and
len(self.get_sink().get_enabled_connections()) > 1
)
if too_many_other_sinks:
self.add_error_message(
- 'Domain "%s" can have only one downstream block' % source_domain)
+ 'Domain "{}" can have only one downstream block'.format(source_domain))
if too_many_other_sources:
self.add_error_message(
- 'Domain "%s" can have only one upstream block' % sink_domain)
+ 'Domain "{}" can have only one upstream block'.format(sink_domain))
+
+ source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen()
+ sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen()
+ if source_size != sink_size:
+ self.add_error_message('Source IO size "{}" does not match sink IO size "{}".'.format(source_size, sink_size))
def get_enabled(self):
"""
@@ -117,11 +137,14 @@ class Connection(Element):
#############################
# Access Ports
#############################
- def get_sink(self): return self._sink
- def get_source(self): return self._source
+ def get_sink(self):
+ return self._sink
+
+ def get_source(self):
+ return self._source
##############################################
- ## Import/Export Methods
+ # Import/Export Methods
##############################################
def export_data(self):
"""
diff --git a/grc/python/Constants.py b/grc/core/Constants.py
index b7a370cad7..9fe805f854 100644
--- a/grc/python/Constants.py
+++ b/grc/core/Constants.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008-2011 Free Software Foundation, Inc.
+Copyright 2008-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,49 +18,53 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
import os
-from os.path import expanduser
import numpy
import stat
-from gnuradio import gr
-_gr_prefs = gr.prefs()
-
-# setup paths
-PATH_SEP = {'/': ':', '\\': ';'}[os.path.sep]
-
-HIER_BLOCKS_LIB_DIR = os.environ.get('GRC_HIER_PATH', expanduser('~/.grc_gnuradio'))
-
-PREFS_FILE = os.environ.get('GRC_PREFS_PATH', expanduser('~/.gnuradio/grc.conf'))
-PREFS_FILE_OLD = os.environ.get('GRC_PREFS_PATH', expanduser('~/.grc'))
-
-BLOCKS_DIRS = filter( # filter blank strings
- lambda x: x, PATH_SEP.join([
- os.environ.get('GRC_BLOCKS_PATH', ''),
- _gr_prefs.get_string('grc', 'local_blocks_path', ''),
- _gr_prefs.get_string('grc', 'global_blocks_path', ''),
- ]).split(PATH_SEP),
-) + [HIER_BLOCKS_LIB_DIR]
-
-# user settings
-XTERM_EXECUTABLE = _gr_prefs.get_string('grc', 'xterm_executable', 'xterm')
-
-# file creation modes
-TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH
-HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH
-
-# data files
+# Data files
DATA_DIR = os.path.dirname(__file__)
-FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
+FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd')
+BLOCK_TREE_DTD = os.path.join(DATA_DIR, 'block_tree.dtd')
BLOCK_DTD = os.path.join(DATA_DIR, 'block.dtd')
DEFAULT_FLOW_GRAPH = os.path.join(DATA_DIR, 'default_flow_graph.grc')
+DOMAIN_DTD = os.path.join(DATA_DIR, 'domain.dtd')
+
+# File format versions:
+# 0: undefined / legacy
+# 1: non-numeric message port keys (label is used instead)
+FLOW_GRAPH_FILE_FORMAT_VERSION = 1
+
+# Param tabs
+DEFAULT_PARAM_TAB = "General"
+ADVANCED_PARAM_TAB = "Advanced"
+
+# Port domains
+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_FLAG_NEED_QT_GUI = 'need_qt_gui'
+BLOCK_FLAG_NEED_WX_GUI = 'need_wx_gui'
+
+# Block States
+BLOCK_DISABLED = 0
+BLOCK_ENABLED = 1
+BLOCK_BYPASSED = 2
+
+# File creation modes
+TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | \
+ stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH
+HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH
-#define types, native python + numpy
+# Define types, native python + numpy
VECTOR_TYPES = (tuple, list, set, numpy.ndarray)
COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128]
REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64]
INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64,
- numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64]
-#cast to tuple for isinstance, concat subtypes
+ numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64]
+# Cast to tuple for isinstance, concat subtypes
COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES)
REAL_TYPES = tuple(REAL_TYPES + INT_TYPES)
INT_TYPES = tuple(INT_TYPES)
@@ -87,7 +91,6 @@ GRC_COLOR_DARK_GREY = '#72706F'
GRC_COLOR_GREY = '#BDBDBD'
GRC_COLOR_WHITE = '#FFFFFF'
-
CORE_TYPES = ( # name, key, sizeof, color
('Complex Float 64', 'fc64', 16, GRC_COLOR_BROWN),
('Complex Float 32', 'fc32', 8, GRC_COLOR_BLUE),
@@ -108,23 +111,25 @@ CORE_TYPES = ( # name, key, sizeof, color
)
ALIAS_TYPES = {
- 'complex' : (8, GRC_COLOR_BLUE),
- 'float' : (4, GRC_COLOR_ORANGE),
- 'int' : (4, GRC_COLOR_TEAL),
- 'short' : (2, GRC_COLOR_YELLOW),
- 'byte' : (1, GRC_COLOR_LIGHT_PURPLE),
+ 'complex': (8, GRC_COLOR_BLUE),
+ 'float': (4, GRC_COLOR_ORANGE),
+ 'int': (4, GRC_COLOR_TEAL),
+ 'short': (2, GRC_COLOR_YELLOW),
+ 'byte': (1, GRC_COLOR_LIGHT_PURPLE),
}
TYPE_TO_COLOR = dict()
TYPE_TO_SIZEOF = dict()
+
for name, key, sizeof, color in CORE_TYPES:
TYPE_TO_COLOR[key] = color
TYPE_TO_SIZEOF[key] = sizeof
+
for key, (sizeof, color) in ALIAS_TYPES.iteritems():
TYPE_TO_COLOR[key] = color
TYPE_TO_SIZEOF[key] = sizeof
-#coloring
+# Coloring
COMPLEX_COLOR_SPEC = '#3399FF'
FLOAT_COLOR_SPEC = '#FF8C69'
INT_COLOR_SPEC = '#00FF99'
diff --git a/grc/base/Element.py b/grc/core/Element.py
index b0f94d0183..b96edb0a72 100644
--- a/grc/base/Element.py
+++ b/grc/core/Element.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008, 2009 Free Software Foundation, Inc.
+Copyright 2008, 2009, 2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -17,6 +17,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
+
class Element(object):
def __init__(self, parent=None):
@@ -32,7 +33,8 @@ class Element(object):
Call this base method before adding error messages in the subclass.
"""
del self._error_messages[:]
- for child in self.get_children(): child.validate()
+ for child in self.get_children():
+ child.validate()
def is_valid(self):
"""
@@ -61,10 +63,10 @@ class Element(object):
Returns:
a list of error message strings
"""
- error_messages = list(self._error_messages) #make a copy
+ error_messages = list(self._error_messages) # Make a copy
for child in filter(lambda c: c.get_enabled() and not c.get_bypassed(), self.get_children()):
for msg in child.get_error_messages():
- error_messages.append("%s:\n\t%s"%(child, msg.replace("\n", "\n\t")))
+ error_messages.append("{}:\n\t{}".format(child, msg.replace("\n", "\n\t")))
return error_messages
def rewrite(self):
@@ -72,27 +74,36 @@ class Element(object):
Rewrite this element and call rewrite on all children.
Call this base method before rewriting the element.
"""
- for child in self.get_children(): child.rewrite()
+ for child in self.get_children():
+ child.rewrite()
+
+ def get_enabled(self):
+ return True
- def get_enabled(self): return True
- def get_bypassed(self): return False
+ def get_bypassed(self):
+ return False
##############################################
- ## Tree-like API
+ # Tree-like API
##############################################
- def get_parent(self): return self._parent
- def get_children(self): return list()
+ def get_parent(self):
+ return self._parent
+
+ def get_children(self):
+ return list()
##############################################
- ## Type testing methods
+ # Type testing
##############################################
- def is_element(self): return True
- def is_platform(self): return False
- def is_flow_graph(self): return False
- def is_connection(self): return False
- def is_block(self): return False
- def is_dummy_block(self): return False
- def is_source(self): return False
- def is_sink(self): return False
- def is_port(self): return False
- def is_param(self): return False
+ is_platform = False
+
+ is_flow_graph = False
+
+ is_block = False
+ is_dummy_block = False
+
+ is_connection = False
+
+ is_port = False
+
+ is_param = False
diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py
new file mode 100644
index 0000000000..313af3107a
--- /dev/null
+++ b/grc/core/FlowGraph.py
@@ -0,0 +1,594 @@
+# Copyright 2008-2015 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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 imp
+import time
+from itertools import ifilter, chain
+from operator import methodcaller
+
+import re
+
+from . import Messages
+from .Constants import FLOW_GRAPH_FILE_FORMAT_VERSION
+from .Element import Element
+from .utils import odict, expr_utils
+
+_variable_matcher = re.compile('^(variable\w*)$')
+_parameter_matcher = re.compile('^(parameter)$')
+_monitors_searcher = re.compile('(ctrlport_monitor)')
+_bussink_searcher = re.compile('^(bus_sink)$')
+_bussrc_searcher = re.compile('^(bus_source)$')
+_bus_struct_sink_searcher = re.compile('^(bus_structure_sink)$')
+_bus_struct_src_searcher = re.compile('^(bus_structure_source)$')
+
+
+class FlowGraph(Element):
+
+ is_flow_graph = True
+
+ def __init__(self, platform):
+ """
+ Make a flow graph from the arguments.
+
+ Args:
+ platform: a platforms with blocks and contrcutors
+
+ Returns:
+ the flow graph object
+ """
+ Element.__init__(self, platform)
+ self._elements = []
+ self._timestamp = time.ctime()
+
+ self.platform = platform # todo: make this a lazy prop
+ self.blocks = []
+ self.connections = []
+
+ self._eval_cache = {}
+ self.namespace = {}
+
+ self.grc_file_path = ''
+ self._options_block = self.new_block('options')
+
+ def __str__(self):
+ return 'FlowGraph - {}({})'.format(self.get_option('title'), self.get_option('id'))
+
+ ##############################################
+ # TODO: Move these to new generator package
+ ##############################################
+ def get_imports(self):
+ """
+ Get a set of all import statments in this flow graph namespace.
+
+ Returns:
+ a set of import statements
+ """
+ imports = sum([block.get_imports() for block in self.get_enabled_blocks()], [])
+ imports = sorted(set(imports))
+ return imports
+
+ def get_variables(self):
+ """
+ Get a list of all variables in this flow graph namespace.
+ Exclude paramterized variables.
+
+ Returns:
+ a sorted list of variable blocks in order of dependency (indep -> dep)
+ """
+ variables = filter(lambda b: _variable_matcher.match(b.get_key()), self.iter_enabled_blocks())
+ return expr_utils.sort_objects(variables, methodcaller('get_id'), methodcaller('get_var_make'))
+
+ def get_parameters(self):
+ """
+ Get a list of all paramterized variables in this flow graph namespace.
+
+ Returns:
+ a list of paramterized variables
+ """
+ parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.iter_enabled_blocks())
+ return parameters
+
+ def get_monitors(self):
+ """
+ Get a list of all ControlPort monitors
+ """
+ monitors = filter(lambda b: _monitors_searcher.search(b.get_key()),
+ self.iter_enabled_blocks())
+ return monitors
+
+ def get_python_modules(self):
+ """Iterate over custom code block ID and Source"""
+ for block in self.iter_enabled_blocks():
+ if block.get_key() == 'epy_module':
+ yield block.get_id(), block.get_param('source_code').get_value()
+
+ def get_bussink(self):
+ bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks())
+
+ for i in bussink:
+ for j in i.get_params():
+ if j.get_name() == 'On/Off' and j.get_value() == 'on':
+ return True
+ return False
+
+ def get_bussrc(self):
+ bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks())
+
+ for i in bussrc:
+ for j in i.get_params():
+ if j.get_name() == 'On/Off' and j.get_value() == 'on':
+ return True
+ return False
+
+ def get_bus_structure_sink(self):
+ bussink = filter(lambda b: _bus_struct_sink_searcher.search(b.get_key()), self.get_enabled_blocks())
+ return bussink
+
+ def get_bus_structure_src(self):
+ bussrc = filter(lambda b: _bus_struct_src_searcher.search(b.get_key()), self.get_enabled_blocks())
+ return bussrc
+
+ def iter_enabled_blocks(self):
+ """
+ Get an iterator of all blocks that are enabled and not bypassed.
+ """
+ return ifilter(methodcaller('get_enabled'), self.blocks)
+
+ def get_enabled_blocks(self):
+ """
+ Get a list of all blocks that are enabled and not bypassed.
+
+ Returns:
+ a list of blocks
+ """
+ return list(self.iter_enabled_blocks())
+
+ def get_bypassed_blocks(self):
+ """
+ Get a list of all blocks that are bypassed.
+
+ Returns:
+ a list of blocks
+ """
+ return filter(methodcaller('get_bypassed'), self.blocks)
+
+ def get_enabled_connections(self):
+ """
+ Get a list of all connections that are enabled.
+
+ Returns:
+ a list of connections
+ """
+ return filter(methodcaller('get_enabled'), self.connections)
+
+ def get_option(self, key):
+ """
+ Get the option for a given key.
+ The option comes from the special options block.
+
+ Args:
+ key: the param key for the options block
+
+ Returns:
+ the value held by that param
+ """
+ return self._options_block.get_param(key).get_evaluated()
+
+ ##############################################
+ # Access Elements
+ ##############################################
+ def get_block(self, id):
+ for block in self.blocks:
+ if block.get_id() == id:
+ return block
+ raise KeyError('No block with ID {!r}'.format(id))
+
+ def get_elements(self):
+ """
+ Get a list of all the elements.
+ Always ensure that the options block is in the list (only once).
+
+ Returns:
+ the element list
+ """
+ options_block_count = self.blocks.count(self._options_block)
+ if not options_block_count:
+ self.blocks.append(self._options_block)
+ for i in range(options_block_count-1):
+ self.blocks.remove(self._options_block)
+
+ return self.blocks + self.connections
+
+ get_children = get_elements
+
+ def rewrite(self):
+ """
+ Flag the namespace to be renewed.
+ """
+
+ self.renew_namespace()
+ for child in chain(self.blocks, self.connections):
+ child.rewrite()
+
+ self.bus_ports_rewrite()
+
+ def renew_namespace(self):
+ namespace = {}
+ # Load imports
+ for expr in self.get_imports():
+ try:
+ exec expr in namespace
+ except:
+ pass
+
+ for id, expr in self.get_python_modules():
+ try:
+ module = imp.new_module(id)
+ exec expr in module.__dict__
+ namespace[id] = module
+ except:
+ pass
+
+ # Load parameters
+ np = {} # params don't know each other
+ for parameter in self.get_parameters():
+ try:
+ value = eval(parameter.get_param('value').to_code(), namespace)
+ np[parameter.get_id()] = value
+ except:
+ pass
+ namespace.update(np) # Merge param namespace
+
+ # Load variables
+ for variable in self.get_variables():
+ try:
+ value = eval(variable.get_var_value(), namespace)
+ namespace[variable.get_id()] = value
+ except:
+ pass
+
+ self.namespace.clear()
+ self._eval_cache.clear()
+ self.namespace.update(namespace)
+
+ def evaluate(self, expr):
+ """
+ Evaluate the expression.
+
+ Args:
+ expr: the string expression
+ @throw Exception bad expression
+
+ Returns:
+ the evaluated data
+ """
+ # Evaluate
+ if not expr:
+ raise Exception('Cannot evaluate empty statement.')
+ return self._eval_cache.setdefault(expr, eval(expr, self.namespace))
+
+ ##############################################
+ # Add/remove stuff
+ ##############################################
+
+ def new_block(self, key):
+ """
+ Get a new block of the specified key.
+ Add the block to the list of elements.
+
+ Args:
+ key: the block key
+
+ Returns:
+ the new block or None if not found
+ """
+ try:
+ block = self.platform.get_new_block(self, key)
+ self.blocks.append(block)
+ except KeyError:
+ block = None
+ return block
+
+ def connect(self, porta, portb):
+ """
+ Create a connection between porta and portb.
+
+ Args:
+ porta: a port
+ portb: another port
+ @throw Exception bad connection
+
+ Returns:
+ the new connection
+ """
+
+ connection = self.platform.Connection(
+ flow_graph=self, porta=porta, portb=portb)
+ self.connections.append(connection)
+ return connection
+
+ def remove_element(self, element):
+ """
+ Remove the element from the list of elements.
+ If the element is a port, remove the whole block.
+ If the element is a block, remove its connections.
+ If the element is a connection, just remove the connection.
+ """
+ if element.is_port:
+ # Found a port, set to parent signal block
+ element = element.get_parent()
+
+ if element in self.blocks:
+ # Remove block, remove all involved connections
+ for port in element.get_ports():
+ map(self.remove_element, port.get_connections())
+ self.blocks.remove(element)
+
+ elif element in self.connections:
+ if element.is_bus():
+ cons_list = []
+ for i in map(lambda a: a.get_connections(), element.get_source().get_associated_ports()):
+ cons_list.extend(i)
+ map(self.remove_element, cons_list)
+ self.connections.remove(element)
+
+ ##############################################
+ # Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this flow graph to nested data.
+ Export all block and connection data.
+
+ Returns:
+ a nested data odict
+ """
+ # sort blocks and connections for nicer diffs
+ blocks = sorted(self.blocks, key=lambda b: (
+ b.get_key() != 'options', # options to the front
+ not b.get_key().startswith('variable'), # then vars
+ str(b)
+ ))
+ connections = sorted(self.connections, key=str)
+ n = odict()
+ n['timestamp'] = self._timestamp
+ n['block'] = [b.export_data() for b in blocks]
+ n['connection'] = [c.export_data() for c in connections]
+ instructions = odict({
+ 'created': '.'.join(self.get_parent().config.version_parts),
+ 'format': FLOW_GRAPH_FILE_FORMAT_VERSION,
+ })
+ return odict({'flow_graph': n, '_instructions': instructions})
+
+ def import_data(self, n):
+ """
+ Import blocks and connections into this flow graph.
+ Clear this flowgraph of all previous blocks and connections.
+ Any blocks or connections in error will be ignored.
+
+ Args:
+ n: the nested data odict
+ """
+ # Remove previous elements
+ del self.blocks[:]
+ del self.connections[:]
+ # set file format
+ try:
+ instructions = n.find('_instructions') or {}
+ file_format = int(instructions.get('format', '0')) or _guess_file_format_1(n)
+ except:
+ file_format = 0
+
+ fg_n = n and n.find('flow_graph') or odict() # use blank data if none provided
+ self._timestamp = fg_n.find('timestamp') or time.ctime()
+
+ # build the blocks
+ self._options_block = self.new_block('options')
+ for block_n in fg_n.findall('block'):
+ key = block_n.find('key')
+ block = self._options_block if key == 'options' else self.new_block(key)
+
+ if not block:
+ # we're before the initial fg update(), so no evaluated values!
+ # --> use raw value instead
+ path_param = self._options_block.get_param('hier_block_src_path')
+ file_path = self.platform.find_file_in_paths(
+ filename=key + '.grc',
+ paths=path_param.get_value(),
+ cwd=self.grc_file_path
+ )
+ if file_path: # grc file found. load and get block
+ self.platform.load_and_generate_flow_graph(file_path)
+ block = self.new_block(key) # can be None
+
+ if not block: # looks like this block key cannot be found
+ # create a dummy block instead
+ block = self.new_block('dummy_block')
+ # Ugly ugly ugly
+ _initialize_dummy_block(block, block_n)
+ print('Block key "%s" not found' % key)
+
+ block.import_data(block_n)
+
+ self.rewrite() # evaluate stuff like nports before adding connections
+
+ # build the connections
+ def verify_and_get_port(key, block, dir):
+ ports = block.get_sinks() if dir == 'sink' else block.get_sources()
+ for port in ports:
+ if key == port.get_key():
+ break
+ if not key.isdigit() and port.get_type() == '' and key == port.get_name():
+ break
+ else:
+ if block.is_dummy_block:
+ port = _dummy_block_add_port(block, key, dir)
+ else:
+ raise LookupError('%s key %r not in %s block keys' % (dir, key, dir))
+ return port
+
+ errors = False
+ for connection_n in fg_n.findall('connection'):
+ # get the block ids and port keys
+ source_block_id = connection_n.find('source_block_id')
+ sink_block_id = connection_n.find('sink_block_id')
+ source_key = connection_n.find('source_key')
+ sink_key = connection_n.find('sink_key')
+ try:
+ source_block = self.get_block(source_block_id)
+ sink_block = self.get_block(sink_block_id)
+
+ # fix old, numeric message ports keys
+ if file_format < 1:
+ source_key, sink_key = _update_old_message_port_keys(
+ source_key, sink_key, source_block, sink_block)
+
+ # build the connection
+ source_port = verify_and_get_port(source_key, source_block, 'source')
+ sink_port = verify_and_get_port(sink_key, sink_block, 'sink')
+ self.connect(source_port, sink_port)
+ except LookupError as e:
+ Messages.send_error_load(
+ 'Connection between {}({}) and {}({}) could not be made.\n\t{}'.format(
+ source_block_id, source_key, sink_block_id, sink_key, e))
+ errors = True
+
+ self.rewrite() # global rewrite
+ return errors
+
+ ##############################################
+ # Needs to go
+ ##############################################
+ def bus_ports_rewrite(self):
+ # todo: move to block.rewrite()
+ for block in self.blocks:
+ for direc in ['source', 'sink']:
+ if direc == 'source':
+ get_p = block.get_sources
+ get_p_gui = block.get_sources_gui
+ bus_structure = block.form_bus_structure('source')
+ else:
+ get_p = block.get_sinks
+ get_p_gui = block.get_sinks_gui
+ 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:
+ for connect in get_p_gui()[-1].get_connections():
+ block.get_parent().remove_element(connect)
+ get_p().remove(get_p_gui()[-1])
+ elif len(get_p_gui()) < len(bus_structure):
+ n = {'name': 'bus', 'type': 'bus'}
+ if True in map(
+ lambda a: isinstance(a.get_nports(), int),
+ get_p()):
+ n['nports'] = str(1)
+
+ times = range(len(get_p_gui()), len(bus_structure))
+
+ for i in times:
+ n['key'] = str(len(get_p()))
+ n = odict(n)
+ port = block.get_parent().get_parent().Port(
+ block=block, n=n, dir=direc)
+ get_p().append(port)
+
+ if 'bus' in map(lambda a: a.get_type(),
+ block.get_sources_gui()):
+ for i in range(len(block.get_sources_gui())):
+ if len(block.get_sources_gui()[
+ i].get_connections()) > 0:
+ source = block.get_sources_gui()[i]
+ sink = []
+
+ for j in range(len(source.get_connections())):
+ sink.append(
+ source.get_connections()[j].get_sink())
+ for elt in source.get_connections():
+ self.remove_element(elt)
+ for j in sink:
+ self.connect(source, j)
+
+
+def _update_old_message_port_keys(source_key, sink_key, source_block, sink_block):
+ """
+ Backward compatibility for message port keys
+
+ Message ports use their names as key (like in the 'connect' method).
+ Flowgraph files from former versions still have numeric keys stored for
+ message connections. These have to be replaced by the name of the
+ respective port. The correct message port is deduced from the integer
+ value of the key (assuming the order has not changed).
+
+ The connection ends are updated only if both ends translate into a
+ message port.
+ """
+ try:
+ # get ports using the "old way" (assuming liner indexed keys)
+ source_port = source_block.get_sources()[int(source_key)]
+ sink_port = sink_block.get_sinks()[int(sink_key)]
+ if source_port.get_type() == "message" and sink_port.get_type() == "message":
+ source_key, sink_key = source_port.get_key(), sink_port.get_key()
+ except (ValueError, IndexError):
+ pass
+ return source_key, sink_key # do nothing
+
+
+def _guess_file_format_1(n):
+ """
+ Try to guess the file format for flow-graph files without version tag
+ """
+ try:
+ has_non_numeric_message_keys = any(not (
+ connection_n.find('source_key').isdigit() and
+ connection_n.find('sink_key').isdigit()
+ ) for connection_n in n.find('flow_graph').findall('connection'))
+ if has_non_numeric_message_keys:
+ return 1
+ except:
+ pass
+ return 0
+
+
+def _initialize_dummy_block(block, block_n):
+ """
+ This is so ugly... dummy-fy a block
+ Modify block object to get the behaviour for a missing block
+ """
+
+ block._key = block_n.find('key')
+ block.is_dummy_block = lambda: True
+ block.is_valid = lambda: False
+ block.get_enabled = lambda: False
+ for param_n in block_n.findall('param'):
+ if param_n['key'] not in block.get_param_keys():
+ new_param_n = odict({'key': param_n['key'], 'name': param_n['key'], 'type': 'string'})
+ params = block.get_parent().get_parent().Param(block=block, n=new_param_n)
+ block.get_params().append(params)
+
+
+def _dummy_block_add_port(block, key, dir):
+ """ This is so ugly... Add a port to a dummy-field block """
+ port_n = odict({'name': '?', 'key': key, 'type': ''})
+ port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir)
+ if port.is_source():
+ block.get_sources().append(port)
+ else:
+ block.get_sinks().append(port)
+ return port
diff --git a/grc/gui/Messages.py b/grc/core/Messages.py
index 551a8ce753..da50487e5b 100644
--- a/grc/gui/Messages.py
+++ b/grc/core/Messages.py
@@ -1,21 +1,20 @@
-"""
-Copyright 2007 Free Software Foundation, Inc.
-This file is part of GNU Radio
+# Copyright 2007, 2015 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 traceback
import sys
@@ -59,20 +58,12 @@ register_messenger(sys.stdout.write)
# Special functions for specific program functionalities
###########################################################################
def send_init(platform):
- p = platform
-
- def get_paths(x):
- return os.path.abspath(os.path.expanduser(x)), x
-
- send('\n'.join([
- "<<< Welcome to %s %s >>>" % (p.get_name(), p.get_version()),
- "",
- "Preferences file: " + p.get_prefs_file(),
- "Block paths:"
- ] + [
- "\t%s" % path + (" (%s)" % opath if opath != path else "")
- for path, opath in map(get_paths, p.get_block_paths())
- ]) + "\n")
+ msg = "<<< Welcome to {config.name} {config.version} >>>\n\n" \
+ "Block paths:\n\t{paths}\n"
+ send(msg.format(
+ config=platform.config,
+ paths="\n\t".join(platform.config.block_paths))
+ )
def send_page_switch(file_path):
diff --git a/grc/core/Param.py b/grc/core/Param.py
new file mode 100644
index 0000000000..d155800c43
--- /dev/null
+++ b/grc/core/Param.py
@@ -0,0 +1,740 @@
+"""
+Copyright 2008-2015 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 ast
+import weakref
+import re
+
+from . import Constants
+from .Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES
+from .Element import Element
+from .utils import odict
+
+# Blacklist certain ids, its not complete, but should help
+import __builtin__
+
+
+ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + dir(__builtin__)
+try:
+ from gnuradio import gr
+ ID_BLACKLIST.extend(attr for attr in dir(gr.top_block()) if not attr.startswith('_'))
+except ImportError:
+ pass
+
+_check_id_matcher = re.compile('^[a-z|A-Z]\w*$')
+_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$')
+
+
+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 "{}" not found in {}.'.format(key, _get_keys(lst)))
+
+
+def num_to_str(num):
+ """ Display logic for numbers """
+ def eng_notation(value, fmt='g'):
+ """Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n"""
+ template = '{:' + fmt + '}{}'
+ magnitude = abs(value)
+ for exp, symbol in zip(range(9, -15-1, -3), 'GMk munpf'):
+ factor = 10 ** exp
+ if magnitude >= factor:
+ return template.format(value / factor, symbol.strip())
+ return template.format(value, '')
+
+ if isinstance(num, COMPLEX_TYPES):
+ num = complex(num) # Cast to python complex
+ if num == 0:
+ return '0'
+ output = eng_notation(num.real) if num.real else ''
+ output += eng_notation(num.imag, '+g' if output else 'g') + 'j' if num.imag else ''
+ return output
+ else:
+ return str(num)
+
+
+class Option(Element):
+
+ def __init__(self, param, n):
+ Element.__init__(self, param)
+ self._name = n.find('name')
+ self._key = n.find('key')
+ self._opts = dict()
+ opts = n.findall('opt')
+ # Test against opts when non enum
+ if not self.get_parent().is_enum() and opts:
+ raise Exception('Options for non-enum types cannot have sub-options')
+ # Extract opts
+ for opt in opts:
+ # Separate the key:value
+ try:
+ key, value = opt.split(':')
+ except:
+ raise Exception('Error separating "{}" into key:value'.format(opt))
+ # Test against repeated keys
+ if key in self._opts:
+ raise Exception('Key "{}" already exists in option'.format(key))
+ # Store the option
+ self._opts[key] = value
+
+ def __str__(self):
+ return 'Option {}({})'.format(self.get_name(), self.get_key())
+
+ def get_name(self):
+ return self._name
+
+ def get_key(self):
+ return self._key
+
+ ##############################################
+ # Access Opts
+ ##############################################
+ def get_opt_keys(self):
+ return self._opts.keys()
+
+ def get_opt(self, key):
+ return self._opts[key]
+
+ def get_opts(self):
+ return self._opts.values()
+
+
+class TemplateArg(object):
+ """
+ A cheetah template argument created from a param.
+ The str of this class evaluates to the param's to code method.
+ The use of this class as a dictionary (enum only) will reveal the enum opts.
+ The __call__ or () method can return the param evaluated to a raw python data type.
+ """
+
+ def __init__(self, param):
+ self._param = weakref.proxy(param)
+
+ def __getitem__(self, item):
+ return str(self._param.get_opt(item)) if self._param.is_enum() else NotImplemented
+
+ def __str__(self):
+ return str(self._param.to_code())
+
+ def __call__(self):
+ return self._param.get_evaluated()
+
+
+class Param(Element):
+
+ is_param = True
+
+ def __init__(self, block, n):
+ """
+ Make a new param from nested data.
+
+ Args:
+ block: the parent element
+ n: the nested odict
+ """
+ # If the base key is a valid param key, copy its data and overlay this params data
+ base_key = n.find('base_key')
+ if base_key and base_key in block.get_param_keys():
+ n_expanded = block.get_param(base_key)._n.copy()
+ n_expanded.update(n)
+ n = n_expanded
+ # Save odict in case this param will be base for another
+ self._n = n
+ # Parse the data
+ self._name = n.find('name')
+ self._key = n.find('key')
+ value = n.find('value') or ''
+ self._type = n.find('type') or 'raw'
+ self._hide = n.find('hide') or ''
+ self._tab_label = n.find('tab') or block.get_param_tab_labels()[0]
+ if self._tab_label not in block.get_param_tab_labels():
+ block.get_param_tab_labels().append(self._tab_label)
+ # Build the param
+ Element.__init__(self, block)
+ # Create the Option objects from the n data
+ self._options = list()
+ self._evaluated = None
+ for option in map(lambda o: Option(param=self, n=o), n.findall('option')):
+ key = option.get_key()
+ # Test against repeated keys
+ if key in self.get_option_keys():
+ raise Exception('Key "{}" already exists in options'.format(key))
+ # Store the option
+ self.get_options().append(option)
+ # Test the enum options
+ if self.is_enum():
+ # Test against options with identical keys
+ if len(set(self.get_option_keys())) != len(self.get_options()):
+ raise Exception('Options keys "{}" are not unique.'.format(self.get_option_keys()))
+ # Test against inconsistent keys in options
+ opt_keys = self.get_options()[0].get_opt_keys()
+ for option in self.get_options():
+ if set(opt_keys) != set(option.get_opt_keys()):
+ raise Exception('Opt keys "{}" are not identical across all options.'.format(opt_keys))
+ # If a value is specified, it must be in the options keys
+ if value or value in self.get_option_keys():
+ self._value = value
+ else:
+ self._value = self.get_option_keys()[0]
+ if self.get_value() not in self.get_option_keys():
+ raise Exception('The value "{}" is not in the possible values of "{}".'.format(self.get_value(), self.get_option_keys()))
+ else:
+ self._value = value or ''
+ self._default = value
+ self._init = False
+ self._hostage_cells = list()
+ self.template_arg = TemplateArg(self)
+
+ def get_types(self):
+ return (
+ 'raw', 'enum',
+ 'complex', 'real', 'float', 'int',
+ 'complex_vector', 'real_vector', 'float_vector', 'int_vector',
+ 'hex', 'string', 'bool',
+ 'file_open', 'file_save', '_multiline', '_multiline_python_external',
+ 'id', 'stream_id',
+ 'grid_pos', 'notebook', 'gui_hint',
+ 'import',
+ )
+
+ def __repr__(self):
+ """
+ Get the repr (nice string format) for this param.
+
+ Returns:
+ the string representation
+ """
+ ##################################################
+ # Truncate helper method
+ ##################################################
+ def _truncate(string, style=0):
+ max_len = max(27 - len(self.get_name()), 3)
+ if len(string) > max_len:
+ if style < 0: # Front truncate
+ string = '...' + string[3-max_len:]
+ elif style == 0: # Center truncate
+ string = string[:max_len/2 - 3] + '...' + string[-max_len/2:]
+ elif style > 0: # Rear truncate
+ string = string[:max_len-3] + '...'
+ return string
+
+ ##################################################
+ # Simple conditions
+ ##################################################
+ if not self.is_valid():
+ return _truncate(self.get_value())
+ if self.get_value() in self.get_option_keys():
+ return self.get_option(self.get_value()).get_name()
+
+ ##################################################
+ # Split up formatting by type
+ ##################################################
+ # Default center truncate
+ truncate = 0
+ e = self.get_evaluated()
+ t = self.get_type()
+ if isinstance(e, bool):
+ return str(e)
+ elif isinstance(e, COMPLEX_TYPES):
+ dt_str = num_to_str(e)
+ elif isinstance(e, VECTOR_TYPES):
+ # Vector types
+ if len(e) > 8:
+ # Large vectors use code
+ dt_str = self.get_value()
+ truncate = 1
+ else:
+ # Small vectors use eval
+ dt_str = ', '.join(map(num_to_str, e))
+ elif t in ('file_open', 'file_save'):
+ dt_str = self.get_value()
+ truncate = -1
+ else:
+ # Other types
+ dt_str = str(e)
+
+ # Done
+ return _truncate(dt_str, truncate)
+
+ def __repr2__(self):
+ """
+ Get the repr (nice string format) for this param.
+
+ Returns:
+ the string representation
+ """
+ if self.is_enum():
+ return self.get_option(self.get_value()).get_name()
+ return self.get_value()
+
+ def __str__(self):
+ return 'Param - {}({})'.format(self.get_name(), self.get_key())
+
+ def get_color(self):
+ """
+ Get the color that represents this param's type.
+
+ Returns:
+ a hex color code.
+ """
+ try:
+ return {
+ # Number types
+ 'complex': Constants.COMPLEX_COLOR_SPEC,
+ 'real': Constants.FLOAT_COLOR_SPEC,
+ 'float': Constants.FLOAT_COLOR_SPEC,
+ 'int': Constants.INT_COLOR_SPEC,
+ # Vector types
+ 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC,
+ 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC,
+ 'float_vector': Constants.FLOAT_VECTOR_COLOR_SPEC,
+ 'int_vector': Constants.INT_VECTOR_COLOR_SPEC,
+ # Special
+ 'bool': Constants.INT_COLOR_SPEC,
+ 'hex': Constants.INT_COLOR_SPEC,
+ 'string': Constants.BYTE_VECTOR_COLOR_SPEC,
+ 'id': Constants.ID_COLOR_SPEC,
+ 'stream_id': Constants.ID_COLOR_SPEC,
+ 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
+ 'notebook': Constants.INT_VECTOR_COLOR_SPEC,
+ 'raw': Constants.WILDCARD_COLOR_SPEC,
+ }[self.get_type()]
+ except:
+ return '#FFFFFF'
+
+ def get_hide(self):
+ """
+ Get the hide value from the base class.
+ Hide the ID parameter for most blocks. Exceptions below.
+ If the parameter controls a port type, vlen, or nports, return part.
+ If the parameter is an empty grid position, return part.
+ These parameters are redundant to display in the flow graph view.
+
+ Returns:
+ hide the hide property string
+ """
+ hide = self.get_parent().resolve_dependencies(self._hide).strip()
+ if hide:
+ return hide
+ # Hide ID in non variable blocks
+ if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()):
+ return 'part'
+ # Hide port controllers for type and nports
+ if self.get_key() in ' '.join(map(lambda p: ' '.join([p._type, p._nports]),
+ self.get_parent().get_ports())):
+ return 'part'
+ # Hide port controllers for vlen, when == 1
+ if self.get_key() in ' '.join(map(
+ lambda p: p._vlen, self.get_parent().get_ports())
+ ):
+ try:
+ if int(self.get_evaluated()) == 1:
+ return 'part'
+ except:
+ pass
+ # Hide empty grid positions
+ if self.get_key() in ('grid_pos', 'notebook') and not self.get_value():
+ return 'part'
+ return hide
+
+ def validate(self):
+ """
+ Validate the param.
+ The value must be evaluated and type must a possible type.
+ """
+ Element.validate(self)
+ if self.get_type() not in self.get_types():
+ self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type()))
+
+ self._evaluated = None
+ try:
+ self._evaluated = self.evaluate()
+ except Exception, e:
+ self.add_error_message(str(e))
+
+ def get_evaluated(self):
+ return self._evaluated
+
+ def evaluate(self):
+ """
+ Evaluate the value.
+
+ Returns:
+ evaluated type
+ """
+ self._init = True
+ self._lisitify_flag = False
+ self._stringify_flag = False
+ self._hostage_cells = list()
+ t = self.get_type()
+ v = self.get_value()
+
+ #########################
+ # Enum Type
+ #########################
+ if self.is_enum():
+ return v
+
+ #########################
+ # Numeric Types
+ #########################
+ elif t in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'):
+ # Raise exception if python cannot evaluate this value
+ try:
+ e = self.get_parent().get_parent().evaluate(v)
+ except Exception, e:
+ raise Exception('Value "{}" cannot be evaluated:\n{}'.format(v, e))
+ # Raise an exception if the data is invalid
+ if t == 'raw':
+ return e
+ elif t == 'complex':
+ if not isinstance(e, COMPLEX_TYPES):
+ raise Exception('Expression "{}" is invalid for type complex.'.format(str(e)))
+ return e
+ elif t == 'real' or t == 'float':
+ if not isinstance(e, REAL_TYPES):
+ raise Exception('Expression "{}" is invalid for type float.'.format(str(e)))
+ return e
+ elif t == 'int':
+ if not isinstance(e, INT_TYPES):
+ raise Exception('Expression "{}" is invalid for type integer.'.format(str(e)))
+ return e
+ elif t == 'hex':
+ return hex(e)
+ elif t == 'bool':
+ if not isinstance(e, bool):
+ raise Exception('Expression "{}" is invalid for type bool.'.format(str(e)))
+ return e
+ else:
+ raise TypeError('Type "{}" not handled'.format(t))
+ #########################
+ # Numeric Vector Types
+ #########################
+ elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'):
+ if not v:
+ # Turn a blank string into an empty list, so it will eval
+ v = '()'
+ # Raise exception if python cannot evaluate this value
+ try:
+ e = self.get_parent().get_parent().evaluate(v)
+ except Exception, e:
+ raise Exception('Value "{}" cannot be evaluated:\n{}'.format(v, e))
+ # Raise an exception if the data is invalid
+ if t == 'complex_vector':
+ if not isinstance(e, VECTOR_TYPES):
+ self._lisitify_flag = True
+ e = [e]
+ if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]):
+ raise Exception('Expression "{}" is invalid for type complex vector.'.format(str(e)))
+ return e
+ elif t == 'real_vector' or t == 'float_vector':
+ if not isinstance(e, VECTOR_TYPES):
+ self._lisitify_flag = True
+ e = [e]
+ if not all([isinstance(ei, REAL_TYPES) for ei in e]):
+ raise Exception('Expression "{}" is invalid for type float vector.'.format(str(e)))
+ return e
+ elif t == 'int_vector':
+ if not isinstance(e, VECTOR_TYPES):
+ self._lisitify_flag = True
+ e = [e]
+ if not all([isinstance(ei, INT_TYPES) for ei in e]):
+ raise Exception('Expression "{}" is invalid for type integer vector.'.format(str(e)))
+ return e
+ #########################
+ # String Types
+ #########################
+ elif t in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'):
+ # Do not check if file/directory exists, that is a runtime issue
+ try:
+ e = self.get_parent().get_parent().evaluate(v)
+ if not isinstance(e, str):
+ raise Exception()
+ except:
+ self._stringify_flag = True
+ e = str(v)
+ if t == '_multiline_python_external':
+ ast.parse(e) # Raises SyntaxError
+ return e
+ #########################
+ # Unique ID Type
+ #########################
+ elif t == 'id':
+ # Can python use this as a variable?
+ if not _check_id_matcher.match(v):
+ raise Exception('ID "{}" must begin with a letter and may contain letters, numbers, and underscores.'.format(v))
+ ids = [param.get_value() for param in self.get_all_params(t)]
+
+ # Id should only appear once, or zero times if block is disabled
+ if ids.count(v) > 1:
+ raise Exception('ID "{}" is not unique.'.format(v))
+ if v in ID_BLACKLIST:
+ raise Exception('ID "{}" is blacklisted.'.format(v))
+ return v
+
+ #########################
+ # Stream ID Type
+ #########################
+ elif t == 'stream_id':
+ # Get a list of all stream ids used in the virtual sinks
+ ids = [param.get_value() for param in filter(
+ lambda p: p.get_parent().is_virtual_sink(),
+ self.get_all_params(t),
+ )]
+ # Check that the virtual sink's stream id is unique
+ if self.get_parent().is_virtual_sink():
+ # Id should only appear once, or zero times if block is disabled
+ if ids.count(v) > 1:
+ raise Exception('Stream ID "{}" is not unique.'.format(v))
+ # Check that the virtual source's steam id is found
+ if self.get_parent().is_virtual_source():
+ if v not in ids:
+ raise Exception('Stream ID "{}" is not found.'.format(v))
+ return v
+
+ #########################
+ # GUI Position/Hint
+ #########################
+ elif t == 'gui_hint':
+ if ':' in v:
+ tab, pos = v.split(':')
+ elif '@' in v:
+ tab, pos = v, ''
+ else:
+ tab, pos = '', v
+
+ if '@' in tab:
+ tab, index = tab.split('@')
+ else:
+ index = '?'
+
+ # TODO: Problem with this code. Produces bad tabs
+ widget_str = ({
+ (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)',
+ (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)',
+ (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)',
+ (False, False): 'self.top_layout.addWidget(%(widget)s)',
+ }[bool(tab), bool(pos)]) % {'tab': tab, 'index': index, 'widget': '%s', 'pos': pos}
+
+ # FIXME: Move replace(...) into the make template of the qtgui blocks
+ # Return a string here
+ class GuiHint(object):
+ def __init__(self, ws):
+ self._ws = ws
+
+ def __call__(self, w):
+ return (self._ws.replace('addWidget', 'addLayout') if 'layout' in w else self._ws) % w
+
+ def __str__(self):
+ return self._ws
+ return GuiHint(widget_str)
+ #########################
+ # Grid Position Type
+ #########################
+ elif t == 'grid_pos':
+ if not v:
+ # Allow for empty grid pos
+ return ''
+ e = self.get_parent().get_parent().evaluate(v)
+ if not isinstance(e, (list, tuple)) or len(e) != 4 or not all([isinstance(ei, int) for ei in e]):
+ raise Exception('A grid position must be a list of 4 integers.')
+ row, col, row_span, col_span = e
+ # Check row, col
+ if row < 0 or col < 0:
+ raise Exception('Row and column must be non-negative.')
+ # Check row span, col span
+ if row_span <= 0 or col_span <= 0:
+ raise Exception('Row and column span must be greater than zero.')
+ # Get hostage cell parent
+ try:
+ my_parent = self.get_parent().get_param('notebook').evaluate()
+ except:
+ my_parent = ''
+ # Calculate hostage cells
+ for r in range(row_span):
+ for c in range(col_span):
+ self._hostage_cells.append((my_parent, (row+r, col+c)))
+ # Avoid collisions
+ params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
+ for param in params:
+ for parent, cell in param._hostage_cells:
+ if (parent, cell) in self._hostage_cells:
+ raise Exception('Another graphical element is using parent "{}", cell "{}".'.format(str(parent), str(cell)))
+ return e
+ #########################
+ # Notebook Page Type
+ #########################
+ elif t == 'notebook':
+ if not v:
+ # Allow for empty notebook
+ return ''
+
+ # Get a list of all notebooks
+ notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks())
+ # Check for notebook param syntax
+ try:
+ notebook_id, page_index = map(str.strip, v.split(','))
+ except:
+ raise Exception('Bad notebook page format.')
+ # Check that the notebook id is valid
+ try:
+ notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0]
+ except:
+ raise Exception('Notebook id "{}" is not an existing notebook id.'.format(notebook_id))
+
+ # Check that page index exists
+ if int(page_index) not in range(len(notebook_block.get_param('labels').evaluate())):
+ raise Exception('Page index "{}" is not a valid index number.'.format(page_index))
+ return notebook_id, page_index
+
+ #########################
+ # Import Type
+ #########################
+ elif t == 'import':
+ # New namespace
+ n = dict()
+ try:
+ exec v in n
+ except ImportError:
+ raise Exception('Import "{}" failed.'.format(v))
+ except Exception:
+ raise Exception('Bad import syntax: "{}".'.format(v))
+ return filter(lambda k: str(k) != '__builtins__', n.keys())
+
+ #########################
+ else:
+ raise TypeError('Type "{}" not handled'.format(t))
+
+ def to_code(self):
+ """
+ Convert the value to code.
+ For string and list types, check the init flag, call evaluate().
+ This ensures that evaluate() was called to set the xxxify_flags.
+
+ Returns:
+ a string representing the code
+ """
+ v = self.get_value()
+ t = self.get_type()
+ # String types
+ if t in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'):
+ if not self._init:
+ self.evaluate()
+ if self._stringify_flag:
+ return '"%s"' % v.replace('"', '\"')
+ else:
+ return v
+ # Vector types
+ elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'):
+ if not self._init:
+ self.evaluate()
+ if self._lisitify_flag:
+ return '(%s, )' % v
+ else:
+ return '(%s)' % v
+ else:
+ return v
+
+ def get_all_params(self, type):
+ """
+ Get all the params from the flowgraph that have the given type.
+
+ Args:
+ type: the specified type
+
+ Returns:
+ a list of params
+ """
+ return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], [])
+
+ def is_enum(self):
+ return self._type == 'enum'
+
+ def get_value(self):
+ value = self._value
+ if self.is_enum() and value not in self.get_option_keys():
+ value = self.get_option_keys()[0]
+ self.set_value(value)
+ return value
+
+ def set_value(self, value):
+ # Must be a string
+ self._value = str(value)
+
+ def set_default(self, value):
+ if self._default == self._value:
+ self.set_value(value)
+ self._default = str(value)
+
+ def get_type(self):
+ return self.get_parent().resolve_dependencies(self._type)
+
+ def get_tab_label(self):
+ return self._tab_label
+
+ def get_name(self):
+ return self.get_parent().resolve_dependencies(self._name).strip()
+
+ def get_key(self):
+ return self._key
+
+ ##############################################
+ # Access Options
+ ##############################################
+ def get_option_keys(self):
+ return _get_keys(self.get_options())
+
+ def get_option(self, key):
+ return _get_elem(self.get_options(), key)
+
+ def get_options(self):
+ return self._options
+
+ ##############################################
+ # Access Opts
+ ##############################################
+ def get_opt_keys(self):
+ return self.get_option(self.get_value()).get_opt_keys()
+
+ def get_opt(self, key):
+ return self.get_option(self.get_value()).get_opt(key)
+
+ def get_opts(self):
+ return self.get_option(self.get_value()).get_opts()
+
+ ##############################################
+ # Import/Export Methods
+ ##############################################
+ def export_data(self):
+ """
+ Export this param's key/value.
+
+ Returns:
+ a nested data odict
+ """
+ n = odict()
+ n['key'] = self.get_key()
+ n['value'] = self.get_value()
+ return n
diff --git a/grc/base/ParseXML.py b/grc/core/ParseXML.py
index e05fc1428d..c9f6541ee7 100644
--- a/grc/base/ParseXML.py
+++ b/grc/core/ParseXML.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008 Free Software Foundation, Inc.
+Copyright 2008, 2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -18,7 +18,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
from lxml import etree
-from . import odict
+
+from .utils import odict
xml_failures = {}
etree.set_default_parser(etree.XMLParser(remove_comments=True))
@@ -42,7 +43,7 @@ def validate_dtd(xml_file, dtd_file=None):
dtd_file: the optional dtd file
@throws Exception validation fails
"""
- # perform parsing, use dtd validation if dtd file is not specified
+ # Perform parsing, use dtd validation if dtd file is not specified
parser = etree.XMLParser(dtd_validation=not dtd_file)
try:
xml = etree.parse(xml_file, parser=parser)
@@ -51,7 +52,7 @@ def validate_dtd(xml_file, dtd_file=None):
if parser.error_log:
raise XMLSyntaxError(parser.error_log)
- # perform dtd validation if the dtd file is specified
+ # Perform dtd validation if the dtd file is specified
if not dtd_file:
return
try:
@@ -100,9 +101,11 @@ def _from_file(xml):
nested_data = odict()
for elem in xml:
key, value = _from_file(elem).items()[0]
- if nested_data.has_key(key): nested_data[key].append(value)
- else: nested_data[key] = [value]
- # delistify if the length of values is 1
+ if key in nested_data:
+ nested_data[key].append(value)
+ else:
+ nested_data[key] = [value]
+ # Delistify if the length of values is 1
for key, values in nested_data.iteritems():
if len(values) == 1:
nested_data[key] = values[0]
@@ -120,7 +123,8 @@ def to_file(nested_data, xml_file):
"""
xml_data = ""
instructions = nested_data.pop('_instructions', None)
- if instructions: # create the processing instruction from the array
+ # Create the processing instruction from the array
+ if instructions:
xml_data += etree.tostring(etree.ProcessingInstruction(
'grc', ' '.join(
"{0}='{1}'".format(*item) for item in instructions.iteritems())
@@ -143,7 +147,7 @@ def _to_file(nested_data):
"""
nodes = list()
for key, values in nested_data.iteritems():
- # listify the values if not a list
+ # Listify the values if not a list
if not isinstance(values, (list, set, tuple)):
values = [values]
for value in values:
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
new file mode 100644
index 0000000000..4c1e6f471a
--- /dev/null
+++ b/grc/core/Platform.py
@@ -0,0 +1,319 @@
+"""
+Copyright 2008-2016 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 os
+import sys
+
+from . import ParseXML, Messages, Constants
+
+from .Config import Config
+from .Element import Element
+from .generator import Generator
+from .FlowGraph import FlowGraph
+from .Connection import Connection
+from .Block import Block
+from .Port import Port
+from .Param import Param
+
+from .utils import odict, extract_docs
+
+
+class Platform(Element):
+
+ Config = Config
+ Generator = Generator
+ FlowGraph = FlowGraph
+ Connection = Connection
+ Block = Block
+ Port = Port
+ Param = Param
+
+ is_platform = True
+
+ def __init__(self, *args, **kwargs):
+ """ Make a platform for GNU Radio """
+ Element.__init__(self)
+
+ self.config = self.Config(*args, **kwargs)
+
+ self.block_docstrings = {}
+ self.block_docstrings_loaded_callback = lambda: None # dummy to be replaced by BlockTreeWindow
+
+ self._docstring_extractor = extract_docs.SubprocessLoader(
+ callback_query_result=self._save_docstring_extraction_result,
+ callback_finished=lambda: self.block_docstrings_loaded_callback()
+ )
+
+ self._block_dtd = Constants.BLOCK_DTD
+ self._default_flow_graph = Constants.DEFAULT_FLOW_GRAPH
+
+ # Create a dummy flow graph for the blocks
+ self._flow_graph = Element(self)
+ self._flow_graph.connections = []
+
+ self.blocks = None
+ self._blocks_n = None
+ self._category_trees_n = None
+ self.domains = {}
+ self.connection_templates = {}
+
+ self._auto_hier_block_generate_chain = set()
+
+ self.load_blocks()
+
+ def __str__(self):
+ return 'Platform - {}({})'.format(self.config.key, self.config.name)
+
+ @staticmethod
+ def find_file_in_paths(filename, paths, cwd):
+ """Checks the provided paths relative to cwd for a certain filename"""
+ if not os.path.isdir(cwd):
+ cwd = os.path.dirname(cwd)
+ if isinstance(paths, str):
+ paths = (p for p in paths.split(':') if p)
+
+ for path in paths:
+ path = os.path.expanduser(path)
+ if not os.path.isabs(path):
+ path = os.path.normpath(os.path.join(cwd, path))
+ file_path = os.path.join(path, filename)
+ if os.path.exists(os.path.normpath(file_path)):
+ return file_path
+
+ def load_and_generate_flow_graph(self, file_path):
+ """Loads a flow graph from file and generates it"""
+ Messages.set_indent(len(self._auto_hier_block_generate_chain))
+ Messages.send('>>> Loading: %r\n' % file_path)
+ if file_path in self._auto_hier_block_generate_chain:
+ Messages.send(' >>> Warning: cyclic hier_block dependency\n')
+ return False
+ self._auto_hier_block_generate_chain.add(file_path)
+ try:
+ flow_graph = self.get_new_flow_graph()
+ flow_graph.grc_file_path = file_path
+ # Other, nested higiter_blocks might be auto-loaded here
+ flow_graph.import_data(self.parse_flow_graph(file_path))
+ flow_graph.rewrite()
+ flow_graph.validate()
+ if not flow_graph.is_valid():
+ raise Exception('Flowgraph invalid')
+ except Exception as e:
+ Messages.send('>>> Load Error: {}: {}\n'.format(file_path, str(e)))
+ return False
+ finally:
+ self._auto_hier_block_generate_chain.discard(file_path)
+ Messages.set_indent(len(self._auto_hier_block_generate_chain))
+
+ try:
+ Messages.send('>>> Generating: {}\n'.format(file_path))
+ generator = self.Generator(flow_graph, file_path)
+ generator.write()
+ except Exception as e:
+ Messages.send('>>> Generate Error: {}: {}\n'.format(file_path, str(e)))
+ return False
+
+ self.load_block_xml(generator.get_file_path_xml())
+ return True
+
+ def load_blocks(self):
+ """load the blocks and block tree from the search paths"""
+ self._docstring_extractor.start()
+ # Reset
+ self.blocks = odict()
+ self._blocks_n = odict()
+ self._category_trees_n = list()
+ self.domains.clear()
+ self.connection_templates.clear()
+ ParseXML.xml_failures.clear()
+ # Try to parse and load blocks
+ for xml_file in self.iter_xml_files():
+ try:
+ if xml_file.endswith("block_tree.xml"):
+ self.load_category_tree_xml(xml_file)
+ elif xml_file.endswith('domain.xml'):
+ self.load_domain_xml(xml_file)
+ else:
+ self.load_block_xml(xml_file)
+ except ParseXML.XMLSyntaxError as e:
+ # print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s' % (e, xml_file)
+ pass
+ except Exception as e:
+ print >> sys.stderr, 'Warning: XML parsing failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file)
+
+ self._docstring_extractor.finish()
+ # self._docstring_extractor.wait()
+
+ def iter_xml_files(self):
+ """Iterator for block descriptions and category trees"""
+ for block_path in self.config.block_paths:
+ if os.path.isfile(block_path):
+ yield block_path
+ elif os.path.isdir(block_path):
+ for dirpath, dirnames, filenames in os.walk(block_path):
+ for filename in sorted(filter(lambda f: f.endswith('.xml'), filenames)):
+ yield os.path.join(dirpath, filename)
+
+ def load_block_xml(self, xml_file):
+ """Load block description from xml file"""
+ # Validate and import
+ ParseXML.validate_dtd(xml_file, self._block_dtd)
+ n = ParseXML.from_file(xml_file).find('block')
+ n['block_wrapper_path'] = xml_file # inject block wrapper path
+ # Get block instance and add it to the list of blocks
+ block = self.Block(self._flow_graph, n)
+ key = block.get_key()
+ if key in self.blocks:
+ print >> sys.stderr, 'Warning: Block with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file)
+ else: # Store the block
+ self.blocks[key] = block
+ self._blocks_n[key] = n
+
+ self._docstring_extractor.query(
+ block.get_key(),
+ block.get_imports(raw=True),
+ block.get_make(raw=True)
+ )
+
+ def load_category_tree_xml(self, xml_file):
+ """Validate and parse category tree file and add it to list"""
+ ParseXML.validate_dtd(xml_file, Constants.BLOCK_TREE_DTD)
+ n = ParseXML.from_file(xml_file).find('cat')
+ self._category_trees_n.append(n)
+
+ def load_domain_xml(self, xml_file):
+ """Load a domain properties and connection templates from XML"""
+ ParseXML.validate_dtd(xml_file, Constants.DOMAIN_DTD)
+ n = ParseXML.from_file(xml_file).find('domain')
+
+ key = n.find('key')
+ if not key:
+ print >> sys.stderr, 'Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file)
+ return
+ if key in self.domains: # test against repeated keys
+ print >> sys.stderr, 'Warning: Domain with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file)
+ return
+
+ #to_bool = lambda s, d: d if s is None else s.lower() not in ('false', 'off', '0', '')
+ def to_bool(s, d):
+ if s is not None:
+ return s.lower() not in ('false', 'off', '0', '')
+ return d
+
+ color = n.find('color') or ''
+ try:
+ import gtk # ugly but handy
+ gtk.gdk.color_parse(color)
+ except (ValueError, ImportError):
+ if color: # no color is okay, default set in GUI
+ print >> sys.stderr, 'Warning: Can\'t parse color code "{}" for domain "{}" '.format(color, key)
+ color = None
+
+ self.domains[key] = dict(
+ name=n.find('name') or key,
+ multiple_sinks=to_bool(n.find('multiple_sinks'), True),
+ multiple_sources=to_bool(n.find('multiple_sources'), False),
+ color=color
+ )
+ for connection_n in n.findall('connection'):
+ key = (connection_n.find('source_domain'), connection_n.find('sink_domain'))
+ if not all(key):
+ print >> sys.stderr, 'Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file)
+ elif key in self.connection_templates:
+ print >> sys.stderr, 'Warning: Connection template "{}" already exists.\n\t{}'.format(key, xml_file)
+ else:
+ self.connection_templates[key] = connection_n.find('make') or ''
+
+ def load_block_tree(self, block_tree):
+ """
+ Load a block tree with categories and blocks.
+ Step 1: Load all blocks from the xml specification.
+ Step 2: Load blocks with builtin category specifications.
+
+ Args:
+ block_tree: the block tree object
+ """
+ # Recursive function to load categories and blocks
+ def load_category(cat_n, parent=None):
+ # Add this category
+ parent = (parent or []) + [cat_n.find('name')]
+ block_tree.add_block(parent)
+ # Recursive call to load sub categories
+ map(lambda c: load_category(c, parent), cat_n.findall('cat'))
+ # Add blocks in this category
+ for block_key in cat_n.findall('block'):
+ if block_key not in self.blocks:
+ print >> sys.stderr, 'Warning: Block key "{}" not found when loading category tree.'.format(block_key)
+ continue
+ block = self.blocks[block_key]
+ # If it exists, the block's category shall not be overridden by the xml tree
+ if not block.get_category():
+ block.set_category(parent)
+
+ # Recursively load the category trees and update the categories for each block
+ for category_tree_n in self._category_trees_n:
+ load_category(category_tree_n)
+
+ # Add blocks to block tree
+ for block in self.blocks.itervalues():
+ # Blocks with empty categories are hidden
+ if not block.get_category():
+ continue
+ block_tree.add_block(block.get_category(), block)
+
+ def _save_docstring_extraction_result(self, key, docstrings):
+ docs = {}
+ for match, docstring in docstrings.iteritems():
+ if not docstring or match.endswith('_sptr'):
+ continue
+ docstring = docstring.replace('\n\n', '\n').strip()
+ docs[match] = docstring
+ self.block_docstrings[key] = docs
+
+ ##############################################
+ # Access
+ ##############################################
+
+ def parse_flow_graph(self, flow_graph_file):
+ """
+ Parse a saved flow graph file.
+ Ensure that the file exists, and passes the dtd check.
+
+ Args:
+ flow_graph_file: the flow graph file
+
+ Returns:
+ nested data
+ @throws exception if the validation fails
+ """
+ flow_graph_file = flow_graph_file or self._default_flow_graph
+ open(flow_graph_file, 'r') # Test open
+ ParseXML.validate_dtd(flow_graph_file, Constants.FLOW_GRAPH_DTD)
+ return ParseXML.from_file(flow_graph_file)
+
+ def get_new_flow_graph(self):
+ return self.FlowGraph(platform=self)
+
+ def get_blocks(self):
+ return self.blocks.values()
+
+ def get_new_block(self, flow_graph, key):
+ return self.Block(flow_graph, n=self._blocks_n[key])
+
+ def get_colors(self):
+ return [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES]
diff --git a/grc/core/Port.py b/grc/core/Port.py
new file mode 100644
index 0000000000..6a8f484082
--- /dev/null
+++ b/grc/core/Port.py
@@ -0,0 +1,404 @@
+"""
+Copyright 2008-2015 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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
+"""
+
+from .Constants import DEFAULT_DOMAIN, GR_STREAM_DOMAIN, GR_MESSAGE_DOMAIN
+from .Element import Element
+
+from . import Constants
+
+
+def _get_source_from_virtual_sink_port(vsp):
+ """
+ Resolve the source port that is connected to the given virtual sink port.
+ Use the get source from virtual source to recursively resolve subsequent ports.
+ """
+ try:
+ return _get_source_from_virtual_source_port(
+ vsp.get_enabled_connections()[0].get_source())
+ except:
+ raise Exception('Could not resolve source for virtual sink port {}'.format(vsp))
+
+
+def _get_source_from_virtual_source_port(vsp, traversed=[]):
+ """
+ Recursively resolve source ports over the virtual connections.
+ Keep track of traversed sources to avoid recursive loops.
+ """
+ if not vsp.get_parent().is_virtual_source():
+ return vsp
+ if vsp in traversed:
+ raise Exception('Loop found when resolving virtual source {}'.format(vsp))
+ try:
+ return _get_source_from_virtual_source_port(
+ _get_source_from_virtual_sink_port(
+ filter( # Get all virtual sinks with a matching stream id
+ lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
+ filter( # Get all enabled blocks that are also virtual sinks
+ lambda b: b.is_virtual_sink(),
+ vsp.get_parent().get_parent().get_enabled_blocks(),
+ ),
+ )[0].get_sinks()[0]
+ ), traversed + [vsp],
+ )
+ except:
+ raise Exception('Could not resolve source for virtual source port {}'.format(vsp))
+
+
+def _get_sink_from_virtual_source_port(vsp):
+ """
+ Resolve the sink port that is connected to the given virtual source port.
+ Use the get sink from virtual sink to recursively resolve subsequent ports.
+ """
+ try:
+ # Could have many connections, but use first
+ return _get_sink_from_virtual_sink_port(
+ vsp.get_enabled_connections()[0].get_sink())
+ except:
+ raise Exception('Could not resolve source for virtual source port {}'.format(vsp))
+
+
+def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
+ """
+ Recursively resolve sink ports over the virtual connections.
+ Keep track of traversed sinks to avoid recursive loops.
+ """
+ if not vsp.get_parent().is_virtual_sink():
+ return vsp
+ if vsp in traversed:
+ raise Exception('Loop found when resolving virtual sink {}'.format(vsp))
+ try:
+ return _get_sink_from_virtual_sink_port(
+ _get_sink_from_virtual_source_port(
+ filter( # Get all virtual source with a matching stream id
+ lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
+ filter( # Get all enabled blocks that are also virtual sinks
+ lambda b: b.is_virtual_source(),
+ vsp.get_parent().get_parent().get_enabled_blocks(),
+ ),
+ )[0].get_sources()[0]
+ ), traversed + [vsp],
+ )
+ except:
+ raise Exception('Could not resolve source for virtual sink port {}'.format(vsp))
+
+
+class Port(Element):
+
+ is_port = True
+
+ def __init__(self, block, n, dir):
+ """
+ Make a new port from nested data.
+
+ Args:
+ block: the parent element
+ n: the nested odict
+ dir: the direction
+ """
+ self._n = n
+ if n['type'] == 'message':
+ n['domain'] = GR_MESSAGE_DOMAIN
+ if 'domain' not in n:
+ n['domain'] = DEFAULT_DOMAIN
+ elif n['domain'] == GR_MESSAGE_DOMAIN:
+ n['key'] = n['name']
+ n['type'] = 'message' # For port color
+ if n['type'] == 'msg':
+ n['key'] = 'msg'
+ if not n.find('key'):
+ n['key'] = str(next(block.port_counters[dir == 'source']))
+
+ # Build the port
+ Element.__init__(self, block)
+ # Grab the data
+ self._name = n['name']
+ self._key = n['key']
+ self._type = n['type'] or ''
+ self._domain = n['domain']
+ self._hide = n.find('hide') or ''
+ self._dir = dir
+ self._hide_evaluated = False # Updated on rewrite()
+
+ self._nports = n.find('nports') or ''
+ self._vlen = n.find('vlen') or ''
+ self._optional = bool(n.find('optional'))
+ self._clones = [] # References to cloned ports (for nports > 1)
+
+ def __str__(self):
+ if self.is_source:
+ return 'Source - {}({})'.format(self.get_name(), self.get_key())
+ if self.is_sink:
+ return 'Sink - {}({})'.format(self.get_name(), self.get_key())
+
+ def get_types(self):
+ return Constants.TYPE_TO_SIZEOF.keys()
+
+ def is_type_empty(self):
+ return not self._n['type']
+
+ def validate(self):
+ Element.validate(self)
+ if self.get_type() not in self.get_types():
+ self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type()))
+ platform = self.get_parent().get_parent().get_parent()
+ if self.get_domain() not in platform.domains:
+ self.add_error_message('Domain key "{}" is not registered.'.format(self.get_domain()))
+ if not self.get_enabled_connections() and not self.get_optional():
+ self.add_error_message('Port is not connected.')
+ # Message port logic
+ if self.get_type() == 'msg':
+ if self.get_nports():
+ self.add_error_message('A port of type "msg" cannot have "nports" set.')
+ if self.get_vlen() != 1:
+ self.add_error_message('A port of type "msg" must have a "vlen" of 1.')
+
+ def rewrite(self):
+ """
+ Handle the port cloning for virtual blocks.
+ """
+ if self.is_type_empty():
+ try:
+ # Clone type and vlen
+ source = self.resolve_empty_type()
+ self._type = str(source.get_type())
+ self._vlen = str(source.get_vlen())
+ except:
+ # Reset type and vlen
+ self._type = ''
+ self._vlen = ''
+
+ Element.rewrite(self)
+ hide = self.get_parent().resolve_dependencies(self._hide).strip().lower()
+ self._hide_evaluated = False if hide in ('false', 'off', '0') else bool(hide)
+
+ # Update domain if was deduced from (dynamic) port type
+ type_ = self.get_type()
+ if self._domain == GR_STREAM_DOMAIN and type_ == "message":
+ self._domain = GR_MESSAGE_DOMAIN
+ self._key = self._name
+ if self._domain == GR_MESSAGE_DOMAIN and type_ != "message":
+ self._domain = GR_STREAM_DOMAIN
+ self._key = '0' # Is rectified in rewrite()
+
+ def resolve_virtual_source(self):
+ if self.get_parent().is_virtual_sink():
+ return _get_source_from_virtual_sink_port(self)
+ if self.get_parent().is_virtual_source():
+ return _get_source_from_virtual_source_port(self)
+
+ def resolve_empty_type(self):
+ if self.is_sink:
+ try:
+ src = _get_source_from_virtual_sink_port(self)
+ if not src.is_type_empty():
+ return src
+ except:
+ pass
+ sink = _get_sink_from_virtual_sink_port(self)
+ if not sink.is_type_empty():
+ return sink
+ if self.is_source:
+ try:
+ src = _get_source_from_virtual_source_port(self)
+ if not src.is_type_empty():
+ return src
+ except:
+ pass
+ sink = _get_sink_from_virtual_source_port(self)
+ if not sink.is_type_empty():
+ return sink
+
+ def get_vlen(self):
+ """
+ Get the vector length.
+ If the evaluation of vlen cannot be cast to an integer, return 1.
+
+ Returns:
+ the vector length or 1
+ """
+ vlen = self.get_parent().resolve_dependencies(self._vlen)
+ try:
+ return int(self.get_parent().get_parent().evaluate(vlen))
+ except:
+ return 1
+
+ def get_nports(self):
+ """
+ Get the number of ports.
+ If already blank, return a blank
+ If the evaluation of nports cannot be cast to a positive integer, return 1.
+
+ Returns:
+ the number of ports or 1
+ """
+ if self._nports == '':
+ return ''
+
+ nports = self.get_parent().resolve_dependencies(self._nports)
+ try:
+ return max(1, int(self.get_parent().get_parent().evaluate(nports)))
+ except:
+ return 1
+
+ def get_optional(self):
+ return bool(self._optional)
+
+ def get_color(self):
+ """
+ Get the color that represents this port's type.
+ Codes differ for ports where the vec length is 1 or greater than 1.
+
+ Returns:
+ a hex color code.
+ """
+ try:
+ color = Constants.TYPE_TO_COLOR[self.get_type()]
+ vlen = self.get_vlen()
+ if vlen == 1:
+ return color
+ color_val = int(color[1:], 16)
+ r = (color_val >> 16) & 0xff
+ g = (color_val >> 8) & 0xff
+ b = (color_val >> 0) & 0xff
+ dark = (0, 0, 30, 50, 70)[min(4, vlen)]
+ r = max(r-dark, 0)
+ g = max(g-dark, 0)
+ b = max(b-dark, 0)
+ # TODO: Change this to .format()
+ return '#%.2x%.2x%.2x' % (r, g, b)
+ except:
+ return '#FFFFFF'
+
+ def get_clones(self):
+ """
+ Get the clones of this master port (nports > 1)
+
+ Returns:
+ a list of ports
+ """
+ return self._clones
+
+ def add_clone(self):
+ """
+ Create a clone of this (master) port and store a reference in self._clones.
+
+ The new port name (and key for message ports) will have index 1... appended.
+ If this is the first clone, this (master) port will get a 0 appended to its name (and key)
+
+ Returns:
+ the cloned port
+ """
+ # Add index to master port name if there are no clones yet
+ if not self._clones:
+ self._name = self._n['name'] + '0'
+ # Also update key for none stream ports
+ if not self._key.isdigit():
+ self._key = self._name
+
+ # Prepare a copy of the odict for the clone
+ n = self._n.copy()
+ # Remove nports from the key so the copy cannot be a duplicator
+ if 'nports' in n:
+ n.pop('nports')
+ n['name'] = self._n['name'] + str(len(self._clones) + 1)
+ # Dummy value 99999 will be fixed later
+ n['key'] = '99999' if self._key.isdigit() else n['name']
+
+ # Clone
+ port = self.__class__(self.get_parent(), n, self._dir)
+ self._clones.append(port)
+ return port
+
+ def remove_clone(self, port):
+ """
+ Remove a cloned port (from the list of clones only)
+ Remove the index 0 of the master port name (and key9 if there are no more clones left
+ """
+ self._clones.remove(port)
+ # Remove index from master port name if there are no more clones
+ if not self._clones:
+ self._name = self._n['name']
+ # Also update key for none stream ports
+ if not self._key.isdigit():
+ self._key = self._name
+
+ def get_name(self):
+ number = ''
+ if self.get_type() == 'bus':
+ busses = filter(lambda a: a._dir == self._dir, self.get_parent().get_ports_gui())
+ number = str(busses.index(self)) + '#' + str(len(self.get_associated_ports()))
+ return self._name + number
+
+ def get_key(self):
+ return self._key
+
+ @property
+ def is_sink(self):
+ return self._dir == 'sink'
+
+ @property
+ def is_source(self):
+ return self._dir == 'source'
+
+ def get_type(self):
+ return self.get_parent().resolve_dependencies(self._type)
+
+ def get_domain(self):
+ return self._domain
+
+ def get_hide(self):
+ return self._hide_evaluated
+
+ def get_connections(self):
+ """
+ Get all connections that use this port.
+
+ Returns:
+ a list of connection objects
+ """
+ connections = self.get_parent().get_parent().connections
+ connections = filter(lambda c: c.get_source() is self or c.get_sink() is self, connections)
+ return connections
+
+ def get_enabled_connections(self):
+ """
+ Get all enabled connections that use this port.
+
+ Returns:
+ a list of connection objects
+ """
+ return filter(lambda c: c.get_enabled(), self.get_connections())
+
+ def get_associated_ports(self):
+ if not self.get_type() == 'bus':
+ return [self]
+ else:
+ if self.is_source:
+ get_ports = self.get_parent().get_sources
+ bus_structure = self.get_parent().current_bus_structure['source']
+ else:
+ get_ports = self.get_parent().get_sinks
+ bus_structure = self.get_parent().current_bus_structure['sink']
+
+ ports = [i for i in get_ports() if not i.get_type() == 'bus']
+ if bus_structure:
+ busses = [i for i in get_ports() if i.get_type() == 'bus']
+ bus_index = busses.index(self)
+ ports = filter(lambda a: ports.index(a) in bus_structure[bus_index], ports)
+ return ports
diff --git a/grc/python/__init__.py b/grc/core/__init__.py
index 8b13789179..8b13789179 100644
--- a/grc/python/__init__.py
+++ b/grc/core/__init__.py
diff --git a/grc/python/block.dtd b/grc/core/block.dtd
index 145f4d8610..145f4d8610 100644
--- a/grc/python/block.dtd
+++ b/grc/core/block.dtd
diff --git a/grc/base/block_tree.dtd b/grc/core/block_tree.dtd
index 9e23576477..9e23576477 100644
--- a/grc/base/block_tree.dtd
+++ b/grc/core/block_tree.dtd
diff --git a/grc/python/default_flow_graph.grc b/grc/core/default_flow_graph.grc
index 059509d34b..059509d34b 100644
--- a/grc/python/default_flow_graph.grc
+++ b/grc/core/default_flow_graph.grc
diff --git a/grc/base/domain.dtd b/grc/core/domain.dtd
index b5b0b8bf39..b5b0b8bf39 100644
--- a/grc/base/domain.dtd
+++ b/grc/core/domain.dtd
diff --git a/grc/base/flow_graph.dtd b/grc/core/flow_graph.dtd
index bdfe1dc059..bdfe1dc059 100644
--- a/grc/base/flow_graph.dtd
+++ b/grc/core/flow_graph.dtd
diff --git a/grc/python/CMakeLists.txt b/grc/core/generator/CMakeLists.txt
index 3f9e273146..4bdd59a7a2 100644
--- a/grc/python/CMakeLists.txt
+++ b/grc/core/generator/CMakeLists.txt
@@ -17,28 +17,16 @@
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
-########################################################################
-GR_PYTHON_INSTALL(FILES
- expr_utils.py
- extract_docs.py
- epy_block_io.py
- Block.py
- Connection.py
- Constants.py
- FlowGraph.py
- Generator.py
- Param.py
- Platform.py
- Port.py
- __init__.py
- DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/python
+file(GLOB py_files "*.py")
+
+GR_PYTHON_INSTALL(
+ FILES ${py_files}
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/generator
COMPONENT "grc"
)
install(FILES
- block.dtd
- default_flow_graph.grc
flow_graph.tmpl
- DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/python
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/generator
COMPONENT "grc"
)
diff --git a/grc/core/generator/FlowGraphProxy.py b/grc/core/generator/FlowGraphProxy.py
new file mode 100644
index 0000000000..3723005576
--- /dev/null
+++ b/grc/core/generator/FlowGraphProxy.py
@@ -0,0 +1,126 @@
+# Copyright 2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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
+
+
+class FlowGraphProxy(object):
+
+ def __init__(self, fg):
+ self._fg = fg
+
+ def __getattr__(self, item):
+ return getattr(self._fg, item)
+
+ def get_hier_block_stream_io(self, direction):
+ """
+ Get a list of stream io signatures for this flow graph.
+
+ Args:
+ direction: a string of 'in' or 'out'
+
+ Returns:
+ a list of dicts with: type, label, vlen, size, optional
+ """
+ return filter(lambda p: p['type'] != "message", self.get_hier_block_io(direction))
+
+ def get_hier_block_message_io(self, direction):
+ """
+ Get a list of message io signatures for this flow graph.
+
+ Args:
+ direction: a string of 'in' or 'out'
+
+ Returns:
+ a list of dicts with: type, label, vlen, size, optional
+ """
+ return filter(lambda p: p['type'] == "message", self.get_hier_block_io(direction))
+
+ def get_hier_block_io(self, direction):
+ """
+ Get a list of io ports for this flow graph.
+
+ Args:
+ direction: a string of 'in' or 'out'
+
+ Returns:
+ a list of dicts with: type, label, vlen, size, optional
+ """
+ pads = self.get_pad_sources() if direction in ('sink', 'in') else \
+ self.get_pad_sinks() if direction in ('source', 'out') else []
+ ports = []
+ for pad in pads:
+ master = {
+ 'label': str(pad.get_param('label').get_evaluated()),
+ 'type': str(pad.get_param('type').get_evaluated()),
+ 'vlen': str(pad.get_param('vlen').get_value()),
+ 'size': pad.get_param('type').get_opt('size'),
+ 'optional': bool(pad.get_param('optional').get_evaluated()),
+ }
+ num_ports = pad.get_param('num_streams').get_evaluated()
+ if num_ports > 1:
+ for i in xrange(num_ports):
+ clone = master.copy()
+ clone['label'] += str(i)
+ ports.append(clone)
+ else:
+ ports.append(master)
+ return ports
+
+ def get_pad_sources(self):
+ """
+ Get a list of pad source blocks sorted by id order.
+
+ Returns:
+ a list of pad source blocks in this flow graph
+ """
+ pads = filter(lambda b: b.get_key() == 'pad_source', self.get_enabled_blocks())
+ return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
+
+ def get_pad_sinks(self):
+ """
+ Get a list of pad sink blocks sorted by id order.
+
+ Returns:
+ a list of pad sink blocks in this flow graph
+ """
+ pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks())
+ return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
+
+ def get_pad_port_global_key(self, port):
+ """
+ Get the key for a port of a pad source/sink to use in connect()
+ This takes into account that pad blocks may have multiple ports
+
+ Returns:
+ the key (str)
+ """
+ key_offset = 0
+ pads = self.get_pad_sources() if port.is_source else self.get_pad_sinks()
+ for pad in pads:
+ # using the block param 'type' instead of the port domain here
+ # to emphasize that hier block generation is domain agnostic
+ is_message_pad = pad.get_param('type').get_evaluated() == "message"
+ if port.get_parent() == pad:
+ if is_message_pad:
+ key = pad.get_param('label').get_value()
+ else:
+ key = str(key_offset + int(port.get_key()))
+ return key
+ else:
+ # assuming we have either only sources or sinks
+ if not is_message_pad:
+ key_offset += len(pad.get_ports())
+ return -1 \ No newline at end of file
diff --git a/grc/python/Generator.py b/grc/core/generator/Generator.py
index 56e3a6e78f..91671072d6 100644
--- a/grc/python/Generator.py
+++ b/grc/core/generator/Generator.py
@@ -1,41 +1,37 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
+# Copyright 2008-2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 codecs
import os
-import sys
-import subprocess
import tempfile
-import shlex
-import codecs
-import re # for shlex_quote
-from distutils.spawn import find_executable
from Cheetah.Template import Template
-from .. gui import Messages
-from .. base import ParseXML
-from .. base import odict
-from .. base.Constants import BLOCK_FLAG_NEED_QT_GUI
+from .FlowGraphProxy import FlowGraphProxy
+from .. import ParseXML, Messages
+from ..Constants import (
+ TOP_BLOCK_FILE_MODE, BLOCK_FLAG_NEED_QT_GUI,
+ HIER_BLOCK_FILE_MODE, BLOCK_DTD
+)
+from ..utils import expr_utils, odict
-from . Constants import TOP_BLOCK_FILE_MODE, FLOW_GRAPH_TEMPLATE, \
- XTERM_EXECUTABLE, HIER_BLOCK_FILE_MODE, HIER_BLOCKS_LIB_DIR, BLOCK_DTD
-from . import expr_utils
+DATA_DIR = os.path.dirname(__file__)
+FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl')
class Generator(object):
@@ -50,19 +46,16 @@ class Generator(object):
flow_graph: the flow graph object
file_path: the path to the grc file
"""
- self._generate_options = flow_graph.get_option('generate_options')
- if self._generate_options == 'hb':
+ self.generate_options = flow_graph.get_option('generate_options')
+ if self.generate_options == 'hb':
generator_cls = HierBlockGenerator
- elif self._generate_options == 'hb_qt_gui':
+ elif self.generate_options == 'hb_qt_gui':
generator_cls = QtHierBlockGenerator
else:
generator_cls = TopBlockGenerator
self._generator = generator_cls(flow_graph, file_path)
- def get_generate_options(self):
- return self._generate_options
-
def __getattr__(self, item):
"""get all other attrib from actual generator object"""
return getattr(self._generator, item)
@@ -78,23 +71,23 @@ class TopBlockGenerator(object):
flow_graph: the flow graph object
file_path: the path to write the file to
"""
- self._flow_graph = flow_graph
+ self._flow_graph = FlowGraphProxy(flow_graph)
self._generate_options = self._flow_graph.get_option('generate_options')
self._mode = TOP_BLOCK_FILE_MODE
dirname = self._dirname = os.path.dirname(file_path)
- # handle the case where the directory is read-only
- # in this case, use the system's temp directory
+ # Handle the case where the directory is read-only
+ # In this case, use the system's temp directory
if not os.access(dirname, os.W_OK):
dirname = tempfile.gettempdir()
filename = self._flow_graph.get_option('id') + '.py'
- self._file_path = os.path.join(dirname, filename)
+ self.file_path = os.path.join(dirname, filename)
def get_file_path(self):
- return self._file_path
+ return self.file_path
def write(self):
"""generate output and write it to files"""
- # do throttle warning
+ # Do throttle warning
throttling_blocks = filter(lambda b: b.throtteling(), self._flow_graph.get_enabled_blocks())
if not throttling_blocks and not self._generate_options.startswith('hb'):
Messages.send_warning("This flow graph may not have flow control: "
@@ -109,48 +102,16 @@ class TopBlockGenerator(object):
"e.g. a hardware source or sink. "
"This is usually undesired. Consider "
"removing the throttle block.")
- # generate
+ # Generate
for filename, data in self._build_python_code_from_template():
with codecs.open(filename, 'w', encoding='utf-8') as fp:
fp.write(data)
- if filename == self.get_file_path():
+ if filename == self.file_path:
try:
os.chmod(filename, self._mode)
except:
pass
- def get_popen(self):
- """
- Execute this python flow graph.
-
- Returns:
- a popen object
- """
- run_command = self._flow_graph.get_option('run_command')
- try:
- run_command = run_command.format(
- python=shlex_quote(sys.executable),
- filename=shlex_quote(self.get_file_path()))
- run_command_args = shlex.split(run_command)
- except Exception as e:
- raise ValueError("Can't parse run command {!r}: {}".format(run_command, e))
-
- # when in no gui mode on linux, use a graphical terminal (looks nice)
- xterm_executable = find_executable(XTERM_EXECUTABLE)
- if self._generate_options == 'no_gui' and xterm_executable:
- run_command_args = [xterm_executable, '-e', run_command]
-
- # this does not reproduce a shell executable command string, if a graphical
- # terminal is used. Passing run_command though shlex_quote would do it but
- # it looks really ugly and confusing in the console panel.
- Messages.send_start_exec(' '.join(run_command_args))
-
- return subprocess.Popen(
- args=run_command_args,
- stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- shell=False, universal_newlines=True
- )
-
def _build_python_code_from_template(self):
"""
Convert the flow graph to python code.
@@ -167,21 +128,21 @@ class TopBlockGenerator(object):
parameters = fg.get_parameters()
monitors = fg.get_monitors()
- # list of blocks not including variables and imports and parameters and disabled
+ # List of blocks not including variables and imports and parameters and disabled
def _get_block_sort_text(block):
code = block.get_make().replace(block.get_id(), ' ')
try:
- code += block.get_param('notebook').get_value() # older gui markup w/ wxgui
+ code += block.get_param('notebook').get_value() # Older gui markup w/ wxgui
except:
pass
try:
- code += block.get_param('gui_hint').get_value() # newer gui markup w/ qtgui
+ code += block.get_param('gui_hint').get_value() # Newer gui markup w/ qtgui
except:
pass
return code
blocks = expr_utils.sort_objects(
- filter(lambda b: b.get_enabled() and not b.get_bypassed(), fg.iter_blocks()),
+ filter(lambda b: b.get_enabled() and not b.get_bypassed(), fg.blocks),
lambda b: b.get_id(), _get_block_sort_text
)
# List of regular blocks (all blocks minus the special ones)
@@ -198,7 +159,8 @@ class TopBlockGenerator(object):
output.append((file_path, src))
# Filter out virtual sink connections
- cf = lambda c: not (c.is_bus() or c.is_msg() or c.get_sink().get_parent().is_virtual_sink())
+ def cf(c):
+ return not (c.is_bus() or c.is_msg() or c.get_sink().get_parent().is_virtual_sink())
connections = filter(cf, fg.get_enabled_connections())
# Get the virtual blocks and resolve their connections
@@ -220,8 +182,7 @@ class TopBlockGenerator(object):
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)
+ source_connection = filter(lambda c: c.get_sink() == block.get_sinks()[0], connections)
# The source connection should never have more than one element.
assert (len(source_connection) == 1)
@@ -229,8 +190,7 @@ class TopBlockGenerator(object):
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):
+ for sink in filter(lambda c: c.get_source() == block.get_sources()[0], connections):
if not sink.get_enabled():
# Ignore disabled connections
continue
@@ -248,23 +208,23 @@ class TopBlockGenerator(object):
c.get_source().get_parent().get_id(), c.get_sink().get_parent().get_id()
))
- connection_templates = fg.get_parent().get_connection_templates()
+ connection_templates = fg.get_parent().connection_templates
msgs = filter(lambda c: c.is_msg(), fg.get_enabled_connections())
- # list of variable names
+ # List of variable names
var_ids = [var.get_id() for var in parameters + variables]
- # prepend self.
+ # Prepend self.
replace_dict = dict([(var_id, 'self.%s' % var_id) for var_id in var_ids])
- # list of callbacks
+ # List of callbacks
callbacks = [
expr_utils.expr_replace(cb, replace_dict)
for cb in sum([block.get_callbacks() for block in fg.get_enabled_blocks()], [])
- ]
- # map var id to callbacks
+ ]
+ # Map var id to callbacks
var_id2cbs = dict([
(var_id, filter(lambda c: expr_utils.get_variable_dependencies(c, [var_id]), callbacks))
for var_id in var_ids
])
- # load the namespace
+ # Load the namespace
namespace = {
'title': title,
'imports': imports,
@@ -279,9 +239,9 @@ class TopBlockGenerator(object):
'generate_options': self._generate_options,
'var_id2cbs': var_id2cbs,
}
- # build the template
+ # Build the template
t = Template(open(FLOW_GRAPH_TEMPLATE, 'r').read(), namespace)
- output.append((self.get_file_path(), str(t)))
+ output.append((self.file_path, str(t)))
return output
@@ -297,10 +257,15 @@ class HierBlockGenerator(TopBlockGenerator):
file_path: where to write the py file (the xml goes into HIER_BLOCK_LIB_DIR)
"""
TopBlockGenerator.__init__(self, flow_graph, file_path)
+ platform = flow_graph.get_parent()
+
+ hier_block_lib_dir = platform.config.hier_block_lib_dir
+ if not os.path.exists(hier_block_lib_dir):
+ os.mkdir(hier_block_lib_dir)
+
self._mode = HIER_BLOCK_FILE_MODE
- self._file_path = os.path.join(HIER_BLOCKS_LIB_DIR,
- self._flow_graph.get_option('id') + '.py')
- self._file_path_xml = self._file_path + '.xml'
+ self.file_path = os.path.join(hier_block_lib_dir, self._flow_graph.get_option('id') + '.py')
+ self._file_path_xml = self.file_path + '.xml'
def get_file_path_xml(self):
return self._file_path_xml
@@ -322,7 +287,7 @@ class HierBlockGenerator(TopBlockGenerator):
Returns:
a xml node tree
"""
- # extract info from the flow graph
+ # Extract info from the flow graph
block_key = self._flow_graph.get_option('id')
parameters = self._flow_graph.get_parameters()
@@ -331,7 +296,7 @@ class HierBlockGenerator(TopBlockGenerator):
return "$"+name
return name
- # build the nested data
+ # Build the nested data
block_n = odict()
block_n['name'] = self._flow_graph.get_option('title') or \
self._flow_graph.get_option('id').replace('_', ' ').title()
@@ -339,7 +304,7 @@ class HierBlockGenerator(TopBlockGenerator):
block_n['category'] = self._flow_graph.get_option('category')
block_n['import'] = "from {0} import {0} # grc-generated hier_block".format(
self._flow_graph.get_option('id'))
- # make data
+ # Make data
if parameters:
block_n['make'] = '{cls}(\n {kwargs},\n)'.format(
cls=block_key,
@@ -349,7 +314,7 @@ class HierBlockGenerator(TopBlockGenerator):
)
else:
block_n['make'] = '{cls}()'.format(cls=block_key)
- # callback data
+ # Callback data
block_n['callback'] = [
'set_{key}(${key})'.format(key=param.get_id()) for param in parameters
]
@@ -364,13 +329,13 @@ class HierBlockGenerator(TopBlockGenerator):
param_n['type'] = 'raw'
block_n['param'].append(param_n)
- # bus stuff
+ # Bus stuff
if self._flow_graph.get_bussink():
block_n['bus_sink'] = '1'
if self._flow_graph.get_bussrc():
block_n['bus_source'] = '1'
- # sink/source ports
+ # Sink/source ports
for direction in ('sink', 'source'):
block_n[direction] = list()
for port in self._flow_graph.get_hier_block_io(direction):
@@ -383,7 +348,7 @@ class HierBlockGenerator(TopBlockGenerator):
port_n['optional'] = '1'
block_n[direction].append(port_n)
- # more bus stuff
+ # More bus stuff
bus_struct_sink = self._flow_graph.get_bus_structure_sink()
if bus_struct_sink:
block_n['bus_structure_sink'] = bus_struct_sink[0].get_param('struct').get_value()
@@ -391,11 +356,11 @@ class HierBlockGenerator(TopBlockGenerator):
if bus_struct_src:
block_n['bus_structure_source'] = bus_struct_src[0].get_param('struct').get_value()
- # documentation
+ # Documentation
block_n['doc'] = "\n".join(field for field in (
self._flow_graph.get_option('author'),
self._flow_graph.get_option('description'),
- self.get_file_path()
+ self.file_path
) if field)
block_n['grc_source'] = str(self._flow_graph.grc_file_path)
@@ -427,21 +392,3 @@ class QtHierBlockGenerator(HierBlockGenerator):
"\n${gui_hint()($win)}"
)
return n
-
-
-###########################################################
-# back-port from python3
-###########################################################
-_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
-
-
-def shlex_quote(s):
- """Return a shell-escaped version of the string *s*."""
- if not s:
- return "''"
- if _find_unsafe(s) is None:
- return s
-
- # use single quotes, and put single quotes into double quotes
- # the string $'b is then quoted as '$'"'"'b'
- return "'" + s.replace("'", "'\"'\"'") + "'"
diff --git a/grc/core/generator/__init__.py b/grc/core/generator/__init__.py
new file mode 100644
index 0000000000..f44b94a85d
--- /dev/null
+++ b/grc/core/generator/__init__.py
@@ -0,0 +1,18 @@
+# Copyright 2008-2015 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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
+
+from Generator import Generator
diff --git a/grc/python/flow_graph.tmpl b/grc/core/generator/flow_graph.tmpl
index bd8025b676..ecdb89390e 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/core/generator/flow_graph.tmpl
@@ -274,8 +274,8 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
self.settings = Qt.QSettings("GNU Radio", "$class_name")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
-
#if $flow_graph.get_option('qt_qss_theme')
+
def setStyleSheetFromFile(self, filename):
try:
if not os.path.exists(filename):
@@ -336,7 +336,12 @@ $short_id#slurp
def argument_parser():
- parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ #set $desc_args = 'usage="%prog: [options]", option_class=eng_option'
+ #if $flow_graph.get_option('description')
+ #set $desc_args += ', description=description'
+ description = $repr($flow_graph.get_option('description'))
+ #end if
+ parser = OptionParser($desc_args)
#for $param in $parameters
#set $type = $param.get_param('type').get_value()
#if $type
diff --git a/grc/core/utils/CMakeLists.txt b/grc/core/utils/CMakeLists.txt
new file mode 100644
index 0000000000..2528fbc43c
--- /dev/null
+++ b/grc/core/utils/CMakeLists.txt
@@ -0,0 +1,26 @@
+# 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.
+
+file(GLOB py_files "*.py")
+
+GR_PYTHON_INSTALL(
+ FILES ${py_files}
+ DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/utils
+ COMPONENT "grc"
+)
diff --git a/grc/core/utils/__init__.py b/grc/core/utils/__init__.py
new file mode 100644
index 0000000000..6b23da2723
--- /dev/null
+++ b/grc/core/utils/__init__.py
@@ -0,0 +1,22 @@
+# Copyright 2008-2015 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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 expr_utils
+import epy_block_io
+import extract_docs
+
+from odict import odict
diff --git a/grc/core/utils/complexity.py b/grc/core/utils/complexity.py
new file mode 100644
index 0000000000..baa8040db4
--- /dev/null
+++ b/grc/core/utils/complexity.py
@@ -0,0 +1,49 @@
+
+def calculate_flowgraph_complexity(flowgraph):
+ """ Determines the complexity of a flowgraph """
+ dbal = 0
+ for block in flowgraph.blocks:
+ # Skip options block
+ if block.get_key() == 'options':
+ continue
+
+ # Don't worry about optional sinks?
+ sink_list = filter(lambda c: not c.get_optional(), block.get_sinks())
+ source_list = filter(lambda c: not c.get_optional(), block.get_sources())
+ sinks = float(len(sink_list))
+ sources = float(len(source_list))
+ base = max(min(sinks, sources), 1)
+
+ # Port ratio multiplier
+ if min(sinks, sources) > 0:
+ multi = sinks / sources
+ multi = (1 / multi) if multi > 1 else multi
+ else:
+ multi = 1
+
+ # Connection ratio multiplier
+ sink_multi = max(float(sum(map(lambda c: len(c.get_connections()), sink_list)) / max(sinks, 1.0)), 1.0)
+ source_multi = max(float(sum(map(lambda c: len(c.get_connections()), source_list)) / max(sources, 1.0)), 1.0)
+ dbal = dbal + (base * multi * sink_multi * source_multi)
+
+ blocks = float(len(flowgraph.blocks))
+ connections = float(len(flowgraph.connections))
+ elements = blocks + connections
+ disabled_connections = len(filter(lambda c: not c.get_enabled(), flowgraph.connections))
+ variables = elements - blocks - connections
+ enabled = float(len(flowgraph.get_enabled_blocks()))
+
+ # Disabled multiplier
+ if enabled > 0:
+ disabled_multi = 1 / (max(1 - ((blocks - enabled) / max(blocks, 1)), 0.05))
+ else:
+ disabled_multi = 1
+
+ # Connection multiplier (How many connections )
+ if (connections - disabled_connections) > 0:
+ conn_multi = 1 / (max(1 - (disabled_connections / max(connections, 1)), 0.05))
+ else:
+ conn_multi = 1
+
+ final = round(max((dbal - 1) * disabled_multi * conn_multi * connections, 0.0) / 1000000, 6)
+ return final
diff --git a/grc/python/epy_block_io.py b/grc/core/utils/epy_block_io.py
index e089908a01..df3a4bbc3e 100644
--- a/grc/python/epy_block_io.py
+++ b/grc/core/utils/epy_block_io.py
@@ -2,9 +2,6 @@
import inspect
import collections
-from gnuradio import gr
-import pmt
-
TYPE_MAP = {
'complex64': 'complex', 'complex': 'complex',
@@ -31,21 +28,27 @@ def _ports(sigs, msgs):
return ports
-def _blk_class(source_code):
+def _find_block_class(source_code, cls):
ns = {}
try:
exec source_code in ns
except Exception as e:
raise ValueError("Can't interpret source code: " + str(e))
for var in ns.itervalues():
- if inspect.isclass(var)and issubclass(var, gr.gateway.gateway_block):
+ if inspect.isclass(var) and issubclass(var, cls):
return var
raise ValueError('No python block class found in code')
def extract(cls):
+ try:
+ from gnuradio import gr
+ import pmt
+ except ImportError:
+ raise EnvironmentError("Can't import GNU Radio")
+
if not inspect.isclass(cls):
- cls = _blk_class(cls)
+ cls = _find_block_class(cls, gr.gateway.gateway_block)
spec = inspect.getargspec(cls.__init__)
defaults = map(repr, spec.defaults or ())
diff --git a/grc/python/expr_utils.py b/grc/core/utils/expr_utils.py
index 9e0b2a4a0a..66911757d6 100644
--- a/grc/python/expr_utils.py
+++ b/grc/core/utils/expr_utils.py
@@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import string
VAR_CHARS = string.letters + string.digits + '_'
+
class graph(object):
"""
Simple graph structure held in a dictionary.
@@ -30,13 +31,16 @@ class graph(object):
def __str__(self): return str(self._graph)
def add_node(self, node_key):
- if self._graph.has_key(node_key): return
+ if node_key in self._graph:
+ return
self._graph[node_key] = set()
def remove_node(self, node_key):
- if not self._graph.has_key(node_key): return
+ if node_key not in self._graph:
+ return
for edges in self._graph.values():
- if node_key in edges: edges.remove(node_key)
+ if node_key in edges:
+ edges.remove(node_key)
self._graph.pop(node_key)
def add_edge(self, src_node_key, dest_node_key):
@@ -45,9 +49,12 @@ class graph(object):
def remove_edge(self, src_node_key, dest_node_key):
self._graph[src_node_key].remove(dest_node_key)
- def get_nodes(self): return self._graph.keys()
+ def get_nodes(self):
+ return self._graph.keys()
+
+ def get_edges(self, node_key):
+ return self._graph[node_key]
- def get_edges(self, node_key): return self._graph[node_key]
def expr_split(expr):
"""
@@ -66,7 +73,8 @@ def expr_split(expr):
quote = ''
for char in expr:
if quote or char in VAR_CHARS:
- if char == quote: quote = ''
+ if char == quote:
+ quote = ''
tok += char
elif char in ("'", '"'):
toks.append(tok)
@@ -79,6 +87,7 @@ def expr_split(expr):
toks.append(tok)
return filter(lambda t: t, toks)
+
def expr_replace(expr, replace_dict):
"""
Search for vars in the expression and add the prepend.
@@ -96,6 +105,7 @@ def expr_replace(expr, replace_dict):
expr_splits[i] = replace_dict[es]
return ''.join(expr_splits)
+
def get_variable_dependencies(expr, vars):
"""
Return a set of variables used in this expression.
@@ -110,6 +120,7 @@ def get_variable_dependencies(expr, vars):
expr_toks = expr_split(expr)
return set(filter(lambda v: v in expr_toks, vars))
+
def get_graph(exprs):
"""
Get a graph representing the variable dependencies
@@ -121,14 +132,17 @@ def get_graph(exprs):
a graph of variable deps
"""
vars = exprs.keys()
- #get dependencies for each expression, load into graph
+ # Get dependencies for each expression, load into graph
var_graph = graph()
- for var in vars: var_graph.add_node(var)
+ for var in vars:
+ var_graph.add_node(var)
for var, expr in exprs.iteritems():
for dep in get_variable_dependencies(expr, vars):
- if dep != var: var_graph.add_edge(dep, var)
+ if dep != var:
+ var_graph.add_edge(dep, var)
return var_graph
+
def sort_variables(exprs):
"""
Get a list of variables in order of dependencies.
@@ -142,17 +156,20 @@ def sort_variables(exprs):
"""
var_graph = get_graph(exprs)
sorted_vars = list()
- #determine dependency order
+ # Determine dependency order
while var_graph.get_nodes():
- #get a list of nodes with no edges
+ # Get a list of nodes with no edges
indep_vars = filter(lambda var: not var_graph.get_edges(var), var_graph.get_nodes())
- if not indep_vars: raise Exception('circular dependency caught in sort_variables')
- #add the indep vars to the end of the list
+ if not indep_vars:
+ raise Exception('circular dependency caught in sort_variables')
+ # Add the indep vars to the end of the list
sorted_vars.extend(sorted(indep_vars))
- #remove each edge-less node from the graph
- for var in indep_vars: var_graph.remove_node(var)
+ # Remove each edge-less node from the graph
+ for var in indep_vars:
+ var_graph.remove_node(var)
return reversed(sorted_vars)
+
def sort_objects(objects, get_id, get_expr):
"""
Sort a list of objects according to their expressions.
@@ -166,12 +183,14 @@ def sort_objects(objects, get_id, get_expr):
a list of sorted objects
"""
id2obj = dict([(get_id(obj), obj) for obj in objects])
- #map obj id to expression code
+ # Map obj id to expression code
id2expr = dict([(get_id(obj), get_expr(obj)) for obj in objects])
- #sort according to dependency
+ # Sort according to dependency
sorted_ids = sort_variables(id2expr)
- #return list of sorted objects
+ # Return list of sorted objects
return [id2obj[id] for id in sorted_ids]
+
if __name__ == '__main__':
- for i in sort_variables({'x':'1', 'y':'x+1', 'a':'x+y', 'b':'y+1', 'c':'a+b+x+y'}): print i
+ for i in sort_variables({'x': '1', 'y': 'x+1', 'a': 'x+y', 'b': 'y+1', 'c': 'a+b+x+y'}):
+ print i
diff --git a/grc/python/extract_docs.py b/grc/core/utils/extract_docs.py
index d8dc4f4e8f..a6e0bc971e 100644
--- a/grc/python/extract_docs.py
+++ b/grc/core/utils/extract_docs.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008-2011 Free Software Foundation, Inc.
+Copyright 2008-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -32,8 +32,8 @@ import itertools
###############################################################################
def docstring_guess_from_key(key):
- """Extract the documentation from the python __doc__ strings
-
+ """
+ Extract the documentation from the python __doc__ strings
By guessing module and constructor names from key
Args:
@@ -65,12 +65,10 @@ def docstring_guess_from_key(key):
else:
return doc_strings
- pattern = re.compile(
- '^' + init_name.replace('_', '_*').replace('x', r'\w') + r'\w*$'
- )
+ pattern = re.compile('^' + init_name.replace('_', '_*').replace('x', r'\w') + r'\w*$')
for match in filter(pattern.match, dir(module)):
try:
- doc_strings[match] = getattr(module, match).__doc__.strip()
+ doc_strings[match] = getattr(module, match).__doc__
except AttributeError:
continue
@@ -78,8 +76,8 @@ def docstring_guess_from_key(key):
def docstring_from_make(key, imports, make):
- """Extract the documentation from the python __doc__ strings
-
+ """
+ Extract the documentation from the python __doc__ strings
By importing it and checking a truncated make
Args:
@@ -95,12 +93,10 @@ def docstring_from_make(key, imports, make):
blk_cls = make.partition('(')[0].strip()
if '$' in blk_cls:
raise ValueError('Not an identifier')
-
ns = dict()
for _import in imports:
exec(_import.strip(), ns)
blk = eval(blk_cls, ns)
-
doc_strings = {key: blk.__doc__}
except (ImportError, AttributeError, SyntaxError, ValueError):
@@ -114,10 +110,11 @@ def docstring_from_make(key, imports, make):
###############################################################################
class SubprocessLoader(object):
- """Start and manage docstring extraction process
-
+ """
+ Start and manage docstring extraction process
Manages subprocess and handles RPC.
"""
+
BOOTSTRAP = "import runpy; runpy.run_path({!r}, run_name='__worker__')"
AUTH_CODE = random.random() # sort out unwanted output of worker process
RESTART = 5 # number of worker restarts before giving up
@@ -134,7 +131,7 @@ class SubprocessLoader(object):
self._last_cmd = None
def start(self):
- """Start the worker process handler thread"""
+ """ Start the worker process handler thread """
if self._thread is not None:
return
self._shutdown.clear()
@@ -143,7 +140,7 @@ class SubprocessLoader(object):
thread.start()
def run_worker(self):
- """Read docstring back from worker stdout and execute callback."""
+ """ Read docstring back from worker stdout and execute callback. """
for _ in range(self.RESTART):
if self._shutdown.is_set():
break
@@ -173,7 +170,7 @@ class SubprocessLoader(object):
self.callback_finished()
def _handle_worker(self):
- """Send commands and responses back from worker."""
+ """ Send commands and responses back from worker. """
assert '1' == self._worker.stdout.read(1)
for cmd, args in iter(self._queue.get, self.DONE):
self._last_cmd = cmd, args
@@ -182,13 +179,13 @@ class SubprocessLoader(object):
self._handle_response(cmd, args)
def _send(self, cmd, args):
- """send a command to worker's stdin"""
+ """ Send a command to worker's stdin """
fd = self._worker.stdin
json.dump((self.AUTH_CODE, cmd, args), fd)
fd.write('\n'.encode())
def _receive(self):
- """receive response from worker's stdout"""
+ """ Receive response from worker's stdout """
for line in iter(self._worker.stdout.readline, ''):
try:
key, cmd, args = json.loads(line, encoding='utf-8')
@@ -201,7 +198,7 @@ class SubprocessLoader(object):
raise IOError("Can't read worker response")
def _handle_response(self, cmd, args):
- """Handle response from worker, call the callback"""
+ """ Handle response from worker, call the callback """
if cmd == 'result':
key, docs = args
self.callback_query_result(key, docs)
@@ -211,7 +208,7 @@ class SubprocessLoader(object):
print >> sys.stderr, "Unknown response:", cmd, args
def query(self, key, imports=None, make=None):
- """request docstring extraction for a certain key"""
+ """ Request docstring extraction for a certain key """
if self._thread is None:
self.start()
if imports and make:
@@ -220,16 +217,16 @@ class SubprocessLoader(object):
self._queue.put(('query_key_only', (key,)))
def finish(self):
- """signal end of requests"""
+ """ Signal end of requests """
self._queue.put(self.DONE)
def wait(self):
- """Wait for the handler thread to die"""
+ """ Wait for the handler thread to die """
if self._thread:
self._thread.join()
def terminate(self):
- """Terminate the worker and wait"""
+ """ Terminate the worker and wait """
self._shutdown.set()
try:
self._worker.terminate()
@@ -243,8 +240,8 @@ class SubprocessLoader(object):
###############################################################################
def worker_main():
- """Main entry point for the docstring extraction process.
-
+ """
+ Main entry point for the docstring extraction process.
Manages RPC with main process through.
Runs a docstring extraction for each key it read on stdin.
"""
diff --git a/grc/base/odict.py b/grc/core/utils/odict.py
index 70ab67d053..20970e947c 100644
--- a/grc/base/odict.py
+++ b/grc/core/utils/odict.py
@@ -1,5 +1,5 @@
"""
-Copyright 2008-2011 Free Software Foundation, Inc.
+Copyright 2008-2015 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
from UserDict import DictMixin
+
class odict(DictMixin):
def __init__(self, d={}):
@@ -57,7 +58,8 @@ class odict(DictMixin):
val: the value for the new entry
"""
index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key)
- if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key))
+ if key in self._keys:
+ raise KeyError('Cannot insert, key "{}" already exists'.format(str(key)))
self._keys.insert(index+1, key)
self._data[key] = val
@@ -72,7 +74,8 @@ class odict(DictMixin):
val: the value for the new entry
"""
index = (pos_key is not None) and self._keys.index(pos_key) or 0
- if key in self._keys: raise KeyError('Cannot insert, key "%s" already exists'%str(key))
+ if key in self._keys:
+ raise KeyError('Cannot insert, key "{}" already exists'.format(str(key)))
self._keys.insert(index, key)
self._data[key] = val
@@ -86,7 +89,8 @@ class odict(DictMixin):
Returns:
the value or None
"""
- if self.has_key(key): return self[key]
+ if key in self:
+ return self[key]
return None
def findall(self, key):
@@ -100,6 +104,8 @@ class odict(DictMixin):
a list of values or empty list
"""
obj = self.find(key)
- if obj is None: obj = list()
- if isinstance(obj, list): return obj
+ if obj is None:
+ obj = list()
+ if isinstance(obj, list):
+ return obj
return [obj]
diff --git a/grc/cpp/README b/grc/cpp/README
deleted file mode 100644
index 3eccc5dbf7..0000000000
--- a/grc/cpp/README
+++ /dev/null
@@ -1,5 +0,0 @@
-GRC could be used to generate c++ based flowgraphs:
-
-* A few base and gui classes would be overridden.
-* Block info could be extracted from the doxygen xml.
-* New flowgraph templates would be designed.
diff --git a/grc/examples/simple/variable_config.grc b/grc/examples/simple/variable_config.grc
deleted file mode 100644
index 0b60abc813..0000000000
--- a/grc/examples/simple/variable_config.grc
+++ /dev/null
@@ -1,561 +0,0 @@
-<?xml version='1.0' encoding='ASCII'?>
-<flow_graph>
- <timestamp>Sat Jul 12 16:15:51 2014</timestamp>
- <block>
- <key>options</key>
- <param>
- <key>id</key>
- <value>variable_config_demo</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>title</key>
- <value>Variable Config Block Demonstration</value>
- </param>
- <param>
- <key>author</key>
- <value>Example</value>
- </param>
- <param>
- <key>description</key>
- <value>Save/Load freq from a config file.</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>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(-1, 2)</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>_coordinate</key>
- <value>(-1, 125)</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>complex</value>
- </param>
- <param>
- <key>samp_rate</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>waveform</key>
- <value>analog.GR_COS_WAVE</value>
- </param>
- <param>
- <key>freq</key>
- <value>freq</value>
- </param>
- <param>
- <key>amp</key>
- <value>1</value>
- </param>
- <param>
- <key>offset</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>_coordinate</key>
- <value>(173, 201)</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>_coordinate</key>
- <value>(392, 233)</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>complex</value>
- </param>
- <param>
- <key>name</key>
- <value>QT GUI Plot</value>
- </param>
- <param>
- <key>fftsize</key>
- <value>1024</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>autoscale</key>
- <value>False</value>
- </param>
- <param>
- <key>average</key>
- <value>1.0</value>
- </param>
- <param>
- <key>ymin</key>
- <value>-140</value>
- </param>
- <param>
- <key>ymax</key>
- <value>10</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>label1</key>
- <value></value>
- </param>
- <param>
- <key>width1</key>
- <value>1</value>
- </param>
- <param>
- <key>color1</key>
- <value>"blue"</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>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>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>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>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>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>_coordinate</key>
- <value>(643, 221)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable_qtgui_range</key>
- <param>
- <key>id</key>
- <value>freq</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>label</key>
- <value>Frequency (Hz)</value>
- </param>
- <param>
- <key>value</key>
- <value>1e3</value>
- </param>
- <param>
- <key>start</key>
- <value>-samp_rate/2</value>
- </param>
- <param>
- <key>stop</key>
- <value>samp_rate/2</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></value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(339, 9)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable_config</key>
- <param>
- <key>id</key>
- <value>freq_init</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>1000</value>
- </param>
- <param>
- <key>type</key>
- <value>real</value>
- </param>
- <param>
- <key>config_file</key>
- <value>/home/mbant/.gnuradio/config.conf</value>
- </param>
- <param>
- <key>section</key>
- <value>main</value>
- </param>
- <param>
- <key>option</key>
- <value>freq</value>
- </param>
- <param>
- <key>writeback</key>
- <value>freq</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(168, 0)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <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>
- <connection>
- <source_block_id>blocks_throttle_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>
- </connection>
-</flow_graph>
diff --git a/grc/examples/xmlrpc/readme.txt b/grc/examples/xmlrpc/readme.txt
deleted file mode 100644
index 056ad1e823..0000000000
--- a/grc/examples/xmlrpc/readme.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-##################################################
-# XMLRPC example
-##################################################
-
-XMLRPC allows software to make remote function calls over http.
-In the case of GRC, one can use XMLRPC to modify variables in a running flow graph.
-See http://www.xmlrpc.com/
-
---- Server Example ---
-Place an "XMLRPC Server" block inside of any flow graph.
-The server will provide set functions for every variable in the flow graph.
-If a variable is called "freq", the server will provide a function set_freq(new_freq).
-Run the server example and experiment with the example client script.
-
--- Client Example --
-The "XMLRPC Client" block will give a variable control over one remove function.
-In the example client, there is one client block and gui control per variable.
-This technique can be used to remotely control a flow graph, perhaps running on a non-gui machine.
diff --git a/grc/examples/xmlrpc/xmlrpc_client.grc b/grc/examples/xmlrpc/xmlrpc_client.grc
deleted file mode 100644
index 45d8af2824..0000000000
--- a/grc/examples/xmlrpc/xmlrpc_client.grc
+++ /dev/null
@@ -1,428 +0,0 @@
-<?xml version='1.0' encoding='ASCII'?>
-<flow_graph>
- <timestamp>Sat Jul 12 17:10:55 2014</timestamp>
- <block>
- <key>options</key>
- <param>
- <key>id</key>
- <value>client_block</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>title</key>
- <value>XMLRPC Client</value>
- </param>
- <param>
- <key>author</key>
- <value>Example</value>
- </param>
- <param>
- <key>description</key>
- <value>example flow graph</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>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(-2, 0)</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>_coordinate</key>
- <value>(13, 172)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>xmlrpc_client</key>
- <param>
- <key>id</key>
- <value>xmlrpc_client</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>addr</key>
- <value>localhost</value>
- </param>
- <param>
- <key>port</key>
- <value>1234</value>
- </param>
- <param>
- <key>callback</key>
- <value>set_freq</value>
- </param>
- <param>
- <key>variable</key>
- <value>freq</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(177, 0)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>xmlrpc_client</key>
- <param>
- <key>id</key>
- <value>xmlrpc_client0</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>addr</key>
- <value>localhost</value>
- </param>
- <param>
- <key>port</key>
- <value>1234</value>
- </param>
- <param>
- <key>callback</key>
- <value>set_ampl</value>
- </param>
- <param>
- <key>variable</key>
- <value>ampl</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(308, 0)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>xmlrpc_client</key>
- <param>
- <key>id</key>
- <value>xmlrpc_client1</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>addr</key>
- <value>localhost</value>
- </param>
- <param>
- <key>port</key>
- <value>1234</value>
- </param>
- <param>
- <key>callback</key>
- <value>set_offset</value>
- </param>
- <param>
- <key>variable</key>
- <value>offset*ampl</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(440, 4)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable_qtgui_range</key>
- <param>
- <key>id</key>
- <value>freq</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>label</key>
- <value>Frequency (Hz)</value>
- </param>
- <param>
- <key>value</key>
- <value>1000</value>
- </param>
- <param>
- <key>start</key>
- <value>0</value>
- </param>
- <param>
- <key>stop</key>
- <value>5e3</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>0,0,1,2</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(209, 165)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable_qtgui_range</key>
- <param>
- <key>id</key>
- <value>ampl</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>label</key>
- <value>Amplitude</value>
- </param>
- <param>
- <key>value</key>
- <value>1</value>
- </param>
- <param>
- <key>start</key>
- <value>0</value>
- </param>
- <param>
- <key>stop</key>
- <value>2</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>1,0,1,2</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(367, 158)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable_qtgui_chooser</key>
- <param>
- <key>id</key>
- <value>offset</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>label</key>
- <value>Offset</value>
- </param>
- <param>
- <key>type</key>
- <value>int</value>
- </param>
- <param>
- <key>num_opts</key>
- <value>3</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>options</key>
- <value>[0, 1, 2]</value>
- </param>
- <param>
- <key>labels</key>
- <value>[]</value>
- </param>
- <param>
- <key>option0</key>
- <value>-1</value>
- </param>
- <param>
- <key>label0</key>
- <value>neg</value>
- </param>
- <param>
- <key>option1</key>
- <value>0</value>
- </param>
- <param>
- <key>label1</key>
- <value>zero</value>
- </param>
- <param>
- <key>option2</key>
- <value>1</value>
- </param>
- <param>
- <key>label2</key>
- <value>pos</value>
- </param>
- <param>
- <key>option3</key>
- <value>3</value>
- </param>
- <param>
- <key>label3</key>
- <value></value>
- </param>
- <param>
- <key>option4</key>
- <value>4</value>
- </param>
- <param>
- <key>label4</key>
- <value></value>
- </param>
- <param>
- <key>widget</key>
- <value>combo_box</value>
- </param>
- <param>
- <key>orient</key>
- <value>Qt.QVBoxLayout</value>
- </param>
- <param>
- <key>gui_hint</key>
- <value>2,0,1,2</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(531, 145)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
-</flow_graph>
diff --git a/grc/examples/xmlrpc/xmlrpc_client_script.py b/grc/examples/xmlrpc/xmlrpc_client_script.py
deleted file mode 100644
index e96c4cbf83..0000000000
--- a/grc/examples/xmlrpc/xmlrpc_client_script.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-
-import time
-import random
-import xmlrpclib
-
-#create server object
-s = xmlrpclib.Server("http://localhost:1234")
-
-#randomly change parameters of the sinusoid
-for i in range(10):
- #generate random values
- new_freq = random.uniform(0, 5000)
- new_ampl = random.uniform(0, 2)
- new_offset = random.uniform(-1, 1)
- #set new values
- time.sleep(1)
- s.set_freq(new_freq)
- time.sleep(1)
- s.set_ampl(new_ampl)
- time.sleep(1)
- s.set_offset(new_offset)
-
diff --git a/grc/examples/xmlrpc/xmlrpc_server.grc b/grc/examples/xmlrpc/xmlrpc_server.grc
deleted file mode 100644
index d210b2694e..0000000000
--- a/grc/examples/xmlrpc/xmlrpc_server.grc
+++ /dev/null
@@ -1,908 +0,0 @@
-<?xml version='1.0' encoding='ASCII'?>
-<flow_graph>
- <timestamp>Sat Jul 12 17:11:40 2014</timestamp>
- <block>
- <key>options</key>
- <param>
- <key>id</key>
- <value>server_block</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>title</key>
- <value>XMLRPC Server</value>
- </param>
- <param>
- <key>author</key>
- <value>Example</value>
- </param>
- <param>
- <key>description</key>
- <value>example flow graph</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>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(0, -1)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>ampl</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>1</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(4, 291)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>freq</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>_coordinate</key>
- <value>(2, 213)</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>_coordinate</key>
- <value>(2, 136)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>offset</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>0</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(3, 366)</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_COS_WAVE</value>
- </param>
- <param>
- <key>freq</key>
- <value>freq</value>
- </param>
- <param>
- <key>amp</key>
- <value>ampl</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>_coordinate</key>
- <value>(175, 0)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>blocks_throttle</key>
- <param>
- <key>id</key>
- <value>blocks_throttle</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>_coordinate</key>
- <value>(399, 35)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>xmlrpc_server</key>
- <param>
- <key>id</key>
- <value>xmlrpc_server</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>addr</key>
- <value>localhost</value>
- </param>
- <param>
- <key>port</key>
- <value>1234</value>
- </param>
- <param>
- <key>alias</key>
- <value></value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(129, 137)</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>Scope Plot</value>
- </param>
- <param>
- <key>size</key>
- <value>1024</value>
- </param>
- <param>
- <key>srate</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>autoscale</key>
- <value>False</value>
- </param>
- <param>
- <key>ymin</key>
- <value>-1</value>
- </param>
- <param>
- <key>ymax</key>
- <value>1</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, 2, 4</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_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>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>_coordinate</key>
- <value>(644, 13)</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>Spectrum Plot</value>
- </param>
- <param>
- <key>fftsize</key>
- <value>1024</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>autoscale</key>
- <value>False</value>
- </param>
- <param>
- <key>average</key>
- <value>1.0</value>
- </param>
- <param>
- <key>ymin</key>
- <value>-140</value>
- </param>
- <param>
- <key>ymax</key>
- <value>10</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>2, 0, 2, 4</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>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>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>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>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>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>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>_coordinate</key>
- <value>(644, 126)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <connection>
- <source_block_id>analog_sig_source_x_0</source_block_id>
- <sink_block_id>blocks_throttle</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>blocks_throttle</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_throttle</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>
-</flow_graph>
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 7766a0a853..077786d4b4 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -17,26 +17,21 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import os
-import subprocess
-from threading import Thread
-import pygtk
-pygtk.require('2.0')
-import gtk
import gobject
+import gtk
+import os
+import subprocess
-from .. base import ParseXML, Constants
-from .. python.Constants import XTERM_EXECUTABLE
-
-from . import Dialogs, Messages, Preferences, Actions
-from .ParserErrorsDialog import ParserErrorsDialog
-from .MainWindow import MainWindow
-from .PropsDialog import PropsDialog
+from . import Dialogs, Preferences, Actions, Executor, Constants
from .FileDialogs import (OpenFlowGraphFileDialog, SaveFlowGraphFileDialog,
- SaveReportsFileDialog, SaveImageFileDialog,
+ SaveReportsFileDialog, SaveScreenShotDialog,
OpenQSSFileDialog)
-from .Constants import DEFAULT_CANVAS_SIZE, IMAGE_FILE_EXTENSION, GR_PREFIX
+from .MainWindow import MainWindow
+from .ParserErrorsDialog import ParserErrorsDialog
+from .PropsDialog import PropsDialog
+
+from ..core import ParseXML, Messages
gobject.threads_init()
@@ -74,8 +69,6 @@ class ActionHandler:
#initialize
self.init_file_paths = file_paths
Actions.APPLICATION_INITIALIZE()
- #enter the mainloop
- gtk.main()
def _handle_key_press(self, widget, event):
"""
@@ -143,6 +136,7 @@ class ActionHandler:
Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB,
Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY,
Actions.FLOW_GRAPH_OPEN_QSS_THEME,
+ Actions.SELECT_ALL,
):
action.set_sensitive(True)
if hasattr(action, 'load_from_preferences'):
@@ -162,6 +156,8 @@ class ActionHandler:
pass #do nothing, update routines below
elif action == Actions.NOTHING_SELECT:
self.get_flow_graph().unselect()
+ elif action == Actions.SELECT_ALL:
+ self.get_flow_graph().select_all()
##################################################
# Enable/Disable
##################################################
@@ -230,7 +226,7 @@ class ActionHandler:
if y < y_min:
y_min = y
- for connection in block.get_connections():
+ for connection in block.connections:
# Get id of connected blocks
source_id = connection.get_source().get_parent().get_id()
@@ -373,7 +369,8 @@ class ActionHandler:
# Window stuff
##################################################
elif action == Actions.ABOUT_WINDOW_DISPLAY:
- Dialogs.AboutDialog(self.get_flow_graph().get_parent())
+ platform = self.get_flow_graph().get_parent()
+ Dialogs.AboutDialog(platform.config)
elif action == Actions.HELP_WINDOW_DISPLAY:
Dialogs.HelpDialog()
elif action == Actions.TYPES_WINDOW_DISPLAY:
@@ -489,12 +486,13 @@ class ActionHandler:
self.main_window.menu_bar.refresh_submenus()
elif action == Actions.FLOW_GRAPH_OPEN_QSS_THEME:
- file_paths = OpenQSSFileDialog(GR_PREFIX + '/share/gnuradio/themes/').run()
+ file_paths = OpenQSSFileDialog(self.platform.config.install_prefix +
+ '/share/gnuradio/themes/').run()
if file_paths:
try:
- from gnuradio import gr
- gr.prefs().set_string("qtgui", "qss", file_paths[0])
- gr.prefs().save()
+ prefs = self.platform.config.prefs
+ prefs.set_string("qtgui", "qss", file_paths[0])
+ prefs.save()
except Exception as e:
Messages.send("Failed to save QSS preference: " + str(e))
elif action == Actions.FLOW_GRAPH_CLOSE:
@@ -521,10 +519,10 @@ class ActionHandler:
self.main_window.tool_bar.refresh_submenus()
self.main_window.menu_bar.refresh_submenus()
elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE:
- file_path = SaveImageFileDialog(self.get_page().get_file_path()).run()
+ file_path, background_transparent = SaveScreenShotDialog(self.get_page().get_file_path()).run()
if file_path is not None:
- pixbuf = self.get_flow_graph().get_drawing_area().get_pixbuf()
- pixbuf.save(file_path, IMAGE_FILE_EXTENSION[1:])
+ pixbuf = self.get_flow_graph().get_drawing_area().get_screenshot(background_transparent)
+ pixbuf.save(file_path, Constants.IMAGE_FILE_EXTENSION[1:])
##################################################
# Gen/Exec/Stop
##################################################
@@ -542,12 +540,13 @@ class ActionHandler:
elif action == Actions.FLOW_GRAPH_EXEC:
if not self.get_page().get_proc():
Actions.FLOW_GRAPH_GEN()
- if Preferences.xterm_missing() != XTERM_EXECUTABLE:
- if not os.path.exists(XTERM_EXECUTABLE):
- Dialogs.MissingXTermDialog(XTERM_EXECUTABLE)
- Preferences.xterm_missing(XTERM_EXECUTABLE)
+ xterm = self.platform.config.xterm_executable
+ if Preferences.xterm_missing() != xterm:
+ if not os.path.exists(xterm):
+ Dialogs.MissingXTermDialog(xterm)
+ Preferences.xterm_missing(xterm)
if self.get_page().get_saved() and self.get_page().get_file_path():
- ExecFlowGraphThread(self)
+ Executor.ExecFlowGraphThread(self)
elif action == Actions.FLOW_GRAPH_KILL:
if self.get_page().get_proc():
try:
@@ -560,7 +559,8 @@ class ActionHandler:
self.platform.load_blocks()
self.main_window.btwin.clear()
self.platform.load_block_tree(self.main_window.btwin)
- Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(bool(ParseXML.xml_failures))
+ Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(bool(
+ ParseXML.xml_failures))
Messages.send_xml_errors_if_any(ParseXML.xml_failures)
# Force a redraw of the graph, by getting the current state and re-importing it
self.main_window.update_pages()
@@ -635,7 +635,7 @@ class ActionHandler:
self.main_window.update()
try: #set the size of the flow graph area (if changed)
new_size = (self.get_flow_graph().get_option('window_size') or
- DEFAULT_CANVAS_SIZE)
+ self.platform.config.default_canvas_size)
if self.get_flow_graph().get_size() != tuple(new_size):
self.get_flow_graph().set_size(*new_size)
except: pass
@@ -653,48 +653,3 @@ class ActionHandler:
Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive)
Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive)
Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() is not None)
-
-class ExecFlowGraphThread(Thread):
- """Execute the flow graph as a new process and wait on it to finish."""
-
- def __init__ (self, action_handler):
- """
- ExecFlowGraphThread constructor.
-
- Args:
- action_handler: an instance of an ActionHandler
- """
- Thread.__init__(self)
- self.update_exec_stop = action_handler.update_exec_stop
- self.flow_graph = action_handler.get_flow_graph()
- #store page and dont use main window calls in run
- self.page = action_handler.get_page()
- #get the popen
- try:
- self.p = self.page.get_generator().get_popen()
- self.page.set_proc(self.p)
- #update
- self.update_exec_stop()
- self.start()
- except Exception, e:
- Messages.send_verbose_exec(str(e))
- Messages.send_end_exec()
-
- def run(self):
- """
- Wait on the executing process by reading from its stdout.
- Use gobject.idle_add when calling functions that modify gtk objects.
- """
- #handle completion
- r = "\n"
- while r:
- gobject.idle_add(Messages.send_verbose_exec, r)
- r = os.read(self.p.stdout.fileno(), 1024)
- self.p.poll()
- gobject.idle_add(self.done)
-
- def done(self):
- """Perform end of execution tasks."""
- Messages.send_end_exec(self.p.returncode)
- self.page.set_proc(None)
- self.update_exec_stop()
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index 9b32b3e601..354e536a82 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -226,6 +226,12 @@ FLOW_GRAPH_REDO = Action(
keypresses=(gtk.keysyms.y, gtk.gdk.CONTROL_MASK),
)
NOTHING_SELECT = Action()
+SELECT_ALL = Action(
+ label='Select _All',
+ tooltip='Select all blocks and connections in the flow graph',
+ stock_id=gtk.STOCK_SELECT_ALL,
+ keypresses=(gtk.keysyms.a, gtk.gdk.CONTROL_MASK),
+)
ELEMENT_SELECT = Action()
ELEMENT_CREATE = Action()
ELEMENT_DELETE = Action(
@@ -386,7 +392,7 @@ FLOW_GRAPH_KILL = Action(
keypresses=(gtk.keysyms.F7, NO_MODS_MASK),
)
FLOW_GRAPH_SCREEN_CAPTURE = Action(
- label='Sc_reen Capture',
+ label='Screen Ca_pture',
tooltip='Create a screen capture of the flow graph',
stock_id=gtk.STOCK_PRINT,
keypresses=(gtk.keysyms.Print, NO_MODS_MASK),
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index 19f041f508..259aa6ed8b 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -82,6 +82,7 @@ MENU_BAR_LIST = (
Actions.BLOCK_COPY,
Actions.BLOCK_PASTE,
Actions.ELEMENT_DELETE,
+ Actions.SELECT_ALL,
None,
Actions.BLOCK_ROTATE_CCW,
Actions.BLOCK_ROTATE_CW,
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index 67b80695fa..95135310b8 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -17,22 +17,24 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from Element import Element
-import Utils
-import Colors
-from .. base import odict
-from .. python.Param import num_to_str
-from Constants import BORDER_PROXIMITY_SENSITIVITY
-from Constants import (
- BLOCK_LABEL_PADDING, PORT_SPACING, PORT_SEPARATION, LABEL_SEPARATION,
- PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS, BLOCK_FONT, PARAM_FONT
-)
-import Actions
import pygtk
pygtk.require('2.0')
import gtk
import pango
+from . import Actions, Colors, Utils
+
+from .Constants import (
+ BLOCK_LABEL_PADDING, PORT_SPACING, PORT_SEPARATION, LABEL_SEPARATION,
+ PORT_BORDER_SEPARATION, POSSIBLE_ROTATIONS, BLOCK_FONT, PARAM_FONT,
+ BORDER_PROXIMITY_SENSITIVITY
+)
+from . Element import Element
+from ..core.Param import num_to_str
+from ..core.utils import odict
+from ..core.utils.complexity import calculate_flowgraph_complexity
+from ..core.Block import Block as _Block
+
BLOCK_MARKUP_TMPL="""\
#set $foreground = $block.is_valid() and 'black' or 'red'
<span foreground="$foreground" font_desc="$font"><b>$encode($block.get_name())</b></span>"""
@@ -52,15 +54,16 @@ COMMENT_COMPLEXITY_MARKUP_TMPL="""\
"""
-
-class Block(Element):
+class Block(Element, _Block):
"""The graphical signal block."""
- def __init__(self):
+ def __init__(self, flow_graph, n):
"""
Block contructor.
Add graphics related params to the block.
"""
+ _Block.__init__(self, flow_graph, n)
+
self.W = 0
self.H = 0
#add the position param
@@ -135,10 +138,10 @@ class Block(Element):
delta_coor: requested delta coordinate (dX, dY) to move
Returns:
- The delta coordinate possible to move while keeping the block on the canvas
+ The delta coordinate possible to move while keeping the block on the canvas
or the input (dX, dY) on failure
"""
- dX, dY = delta_coor
+ dX, dY = delta_coor
try:
fgW, fgH = self.get_parent().get_size()
@@ -147,7 +150,7 @@ class Block(Element):
sW, sH = self.W, self.H
else:
sW, sH = self.H, self.W
-
+
if x + dX < 0:
dX = -x
elif dX + x + sW >= fgW:
@@ -159,7 +162,7 @@ class Block(Element):
except:
pass
- return ( dX, dY )
+ return ( dX, dY )
def get_rotation(self):
"""
@@ -193,7 +196,7 @@ class Block(Element):
def create_labels(self):
"""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._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
@@ -204,7 +207,7 @@ class Block(Element):
layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, font=BLOCK_FONT))
self.label_width, self.label_height = layout.get_pixel_size()
#display the params
- if self.is_dummy_block():
+ if self.is_dummy_block:
markups = [
'<span foreground="black" font_desc="{font}"><b>key: </b>{key}</span>'.format(font=PARAM_FONT, key=self._key)
]
@@ -271,7 +274,8 @@ class Block(Element):
# Show the flowgraph complexity on the top block if enabled
if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and self.get_key() == "options":
- complexity = "Complexity: {}bal".format(num_to_str(self.get_parent().get_complexity()))
+ complexity = calculate_flowgraph_complexity(self.get_parent())
+ complexity = "Complexity: {}bal".format(num_to_str(complexity))
layout = gtk.DrawingArea().create_pango_layout('')
layout.set_markup(Utils.parse_template(COMMENT_COMPLEXITY_MARKUP_TMPL,
@@ -311,7 +315,7 @@ class Block(Element):
Element.draw(
self, gc, window, bg_color=self._bg_color,
border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or
- self.is_dummy_block() and Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR,
+ self.is_dummy_block and Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR,
)
#draw label image
if self.is_horizontal():
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
index 6b3ebf7807..4279e8c61d 100644
--- a/grc/gui/BlockTreeWindow.py
+++ b/grc/gui/BlockTreeWindow.py
@@ -30,12 +30,27 @@ KEY_INDEX = 1
DOC_INDEX = 2
DOC_MARKUP_TMPL = """\
-#if $doc
-#if len($doc) > 1000
-#set $doc = $doc[:1000] + '...'
+#set $docs = []
+#if $doc.get('')
+ #set $docs += $doc.pop('').splitlines() + ['']
#end if
-$encode($doc)#slurp
-#else
+#for b, d in $doc.iteritems()
+ #set $docs += ['--- {0} ---'.format(b)] + d.splitlines() + ['']
+#end for
+#set $len_out = 0
+#for $n, $line in $enumerate($docs[:-1])
+#if $n
+
+#end if
+$encode($line)#slurp
+#set $len_out += $len($line)
+#if $n > 10 or $len_out > 500
+
+...#slurp
+#break
+#end if
+#end for
+#if $len_out == 0
undocumented#slurp
#end if"""
@@ -129,8 +144,10 @@ class BlockTreeWindow(gtk.VBox):
category: the category list or path string
block: the block object or None
"""
- if treestore is None: treestore = self.treestore
- if categories is None: categories = self._categories
+ if treestore is None:
+ treestore = self.treestore
+ if categories is None:
+ categories = self._categories
if isinstance(category, (str, unicode)): category = category.split('/')
category = tuple(filter(lambda x: x, category)) # tuple is hashable
@@ -138,17 +155,18 @@ class BlockTreeWindow(gtk.VBox):
for i, cat_name in enumerate(category):
sub_category = category[:i+1]
if sub_category not in categories:
- iter = treestore.insert_before(categories[sub_category[:-1]], None)
- treestore.set_value(iter, NAME_INDEX, '[ %s ]'%cat_name)
- treestore.set_value(iter, KEY_INDEX, '')
- treestore.set_value(iter, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name))
- categories[sub_category] = iter
+ iter_ = treestore.insert_before(categories[sub_category[:-1]], None)
+ treestore.set_value(iter_, NAME_INDEX, cat_name)
+ treestore.set_value(iter_, KEY_INDEX, '')
+ treestore.set_value(iter_, DOC_INDEX, Utils.parse_template(CAT_MARKUP_TMPL, cat=cat_name))
+ categories[sub_category] = iter_
# add block
- if block is None: return
- iter = treestore.insert_before(categories[category], None)
- treestore.set_value(iter, NAME_INDEX, block.get_name())
- treestore.set_value(iter, KEY_INDEX, block.get_key())
- treestore.set_value(iter, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()))
+ if block is None:
+ return
+ iter_ = treestore.insert_before(categories[category], None)
+ treestore.set_value(iter_, NAME_INDEX, block.get_name())
+ treestore.set_value(iter_, KEY_INDEX, block.get_key())
+ treestore.set_value(iter_, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()))
def update_docs(self):
"""Update the documentation column of every block"""
@@ -157,7 +175,7 @@ class BlockTreeWindow(gtk.VBox):
if model.iter_has_child(iter_):
return # category node, no doc string
key = model.get_value(iter_, KEY_INDEX)
- block = self.platform.get_block(key)
+ block = self.platform.blocks[key]
doc = Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc())
model.set_value(iter_, DOC_INDEX, doc)
@@ -210,8 +228,8 @@ class BlockTreeWindow(gtk.VBox):
self.treeview.set_model(self.treestore)
self.treeview.collapse_all()
else:
- blocks = self.get_flow_graph().get_parent().get_blocks()
- matching_blocks = filter(lambda b: key in b.get_key().lower() or key in b.get_name().lower(), blocks)
+ matching_blocks = filter(lambda b: key in b.get_key().lower() or key in b.get_name().lower(),
+ self.platform.blocks.values())
self.treestore_search.clear()
self._categories_search = {tuple(): None}
diff --git a/grc/gui/CMakeLists.txt b/grc/gui/CMakeLists.txt
index 99140df7c4..aa9592b351 100644
--- a/grc/gui/CMakeLists.txt
+++ b/grc/gui/CMakeLists.txt
@@ -17,34 +17,10 @@
# the Free Software Foundation, Inc., 51 Franklin Street,
# Boston, MA 02110-1301, USA.
-########################################################################
-GR_PYTHON_INSTALL(FILES
- external_editor.py
- Block.py
- Colors.py
- Constants.py
- Connection.py
- Element.py
- FlowGraph.py
- Param.py
- Platform.py
- Port.py
- Utils.py
- ActionHandler.py
- Actions.py
- Bars.py
- BlockTreeWindow.py
- Dialogs.py
- DrawingArea.py
- FileDialogs.py
- MainWindow.py
- Messages.py
- NotebookPage.py
- ParserErrorsDialog.py
- PropsDialog.py
- Preferences.py
- StateCache.py
- __init__.py
+file(GLOB py_files "*.py")
+
+GR_PYTHON_INSTALL(
+ FILES ${py_files}
DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/gui
COMPONENT "grc"
)
diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py
index 52c95e8edf..050b363cdd 100644
--- a/grc/gui/Colors.py
+++ b/grc/gui/Colors.py
@@ -33,8 +33,9 @@ try:
PARAM_ENTRY_TEXT_COLOR = get_color('black')
ENTRYENUM_CUSTOM_COLOR = get_color('#EEEEEE')
#flow graph color constants
- FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFF9FF')
+ FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFFFFF')
COMMENT_BACKGROUND_COLOR = get_color('#F3F3F3')
+ FLOWGRAPH_EDGE_COLOR = COMMENT_BACKGROUND_COLOR
#block color constants
BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
diff --git a/grc/gui/Config.py b/grc/gui/Config.py
new file mode 100644
index 0000000000..9b0c5d4afe
--- /dev/null
+++ b/grc/gui/Config.py
@@ -0,0 +1,74 @@
+"""
+Copyright 2016 Free Software Foundation, Inc.
+This file is part of GNU Radio
+
+GNU Radio Companion 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 2
+of the License, or (at your option) any later version.
+
+GNU Radio Companion 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 sys
+import os
+from ..core.Config import Config as _Config
+from . import Constants
+
+
+class Config(_Config):
+
+ name = 'GNU Radio Companion'
+
+ gui_prefs_file = os.environ.get(
+ 'GRC_PREFS_PATH', os.path.expanduser('~/.gnuradio/grc.conf'))
+
+ def __init__(self, install_prefix, *args, **kwargs):
+ _Config.__init__(self, *args, **kwargs)
+ self.install_prefix = install_prefix
+ Constants.update_font_size(self.font_size)
+
+ @property
+ def editor(self):
+ return self.prefs.get_string('grc', 'editor', '')
+
+ @editor.setter
+ def editor(self, value):
+ self.prefs.get_string('grc', 'editor', value)
+ self.prefs.save()
+
+ @property
+ def xterm_executable(self):
+ return self.prefs.get_string('grc', 'xterm_executable', 'xterm')
+
+ @property
+ def default_canvas_size(self):
+ try: # ugly, but matches current code style
+ raw = self.prefs.get_string('grc', 'canvas_default_size', '1280, 1024')
+ value = tuple(int(x.strip('() ')) for x in raw.split(','))
+ if len(value) != 2 or not all(300 < x < 4096 for x in value):
+ raise Exception()
+ return value
+ except:
+ print >> sys.stderr, "Error: invalid 'canvas_default_size' setting."
+ return Constants.DEFAULT_CANVAS_SIZE_DEFAULT
+
+ @property
+ def font_size(self):
+ try: # ugly, but matches current code style
+ font_size = self.prefs.get_long('grc', 'canvas_font_size',
+ Constants.DEFAULT_FONT_SIZE)
+ if font_size <= 0:
+ raise Exception()
+ except:
+ font_size = Constants.DEFAULT_FONT_SIZE
+ print >> sys.stderr, "Error: invalid 'canvas_font_size' setting."
+
+ return font_size
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index badf8e8a82..50361c19d0 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -17,15 +17,18 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import Utils
-from Element import Element
+import gtk
+
import Colors
+import Utils
from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT
-import gtk
+from Element import Element
+
+from ..core.Constants import GR_MESSAGE_DOMAIN
+from ..core.Connection import Connection as _Connection
-from .. base.Constants import GR_MESSAGE_DOMAIN
-class Connection(Element):
+class Connection(Element, _Connection):
"""
A graphical connection for ports.
The connection has 2 parts, the arrow and the wire.
@@ -35,8 +38,9 @@ class Connection(Element):
The arrow coloring exposes the enabled and valid states.
"""
- def __init__(self):
+ def __init__(self, **kwargs):
Element.__init__(self)
+ _Connection.__init__(self, **kwargs)
# can't use Colors.CONNECTION_ENABLED_COLOR here, might not be defined (grcc)
self._bg_color = self._arrow_color = self._color = None
@@ -88,7 +92,7 @@ class Connection(Element):
if not source_domain == sink_domain == GR_MESSAGE_DOMAIN \
else gtk.gdk.LINE_ON_OFF_DASH
get_domain_color = lambda d: Colors.get_color((
- self.get_parent().get_parent().get_domain(d) or {}
+ self.get_parent().get_parent().domains.get(d, {})
).get('color') or Colors.DEFAULT_DOMAIN_COLOR_CODE)
self._color = get_domain_color(source_domain)
self._bg_color = get_domain_color(sink_domain)
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 741c6fda95..e267c6ca02 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -17,18 +17,10 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import os
-import sys
-
-import pygtk
-pygtk.require('2.0')
import gtk
-from gnuradio import gr
+from ..core.Constants import *
-prefs = gr.prefs()
-GR_PREFIX = gr.prefix()
-EDITOR = prefs.get_string('grc', 'editor', '')
# default path for the open/save dialogs
DEFAULT_FILE_PATH = os.getcwd()
@@ -50,28 +42,12 @@ MIN_DIALOG_HEIGHT = 500
DEFAULT_BLOCKS_WINDOW_WIDTH = 100
DEFAULT_REPORTS_WINDOW_WIDTH = 100
-try: # ugly, but matches current code style
- raw = prefs.get_string('grc', 'canvas_default_size', '1280, 1024')
- DEFAULT_CANVAS_SIZE = tuple(int(x.strip('() ')) for x in raw.split(','))
- if len(DEFAULT_CANVAS_SIZE) != 2 or not all(300 < x < 4096 for x in DEFAULT_CANVAS_SIZE):
- raise Exception()
-except:
- DEFAULT_CANVAS_SIZE = 1280, 1024
- print >> sys.stderr, "Error: invalid 'canvas_default_size' setting."
-
-# flow-graph canvas fonts
-try: # ugly, but matches current code style
- FONT_SIZE = prefs.get_long('grc', 'canvas_font_size', 8)
- if FONT_SIZE <= 0:
- raise Exception()
-except:
- FONT_SIZE = 8
- print >> sys.stderr, "Error: invalid 'canvas_font_size' setting."
-FONT_FAMILY = "Sans"
-BLOCK_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE)
-PORT_FONT = BLOCK_FONT
-PARAM_FONT = "%s %f" % (FONT_FAMILY, FONT_SIZE - 0.5)
+DEFAULT_CANVAS_SIZE_DEFAULT = 1280, 1024
+FONT_SIZE = DEFAULT_FONT_SIZE = 8
+FONT_FAMILY = "Sans"
+BLOCK_FONT = PORT_FONT = "Sans 8"
+PARAM_FONT = "Sans 7.5"
# size of the state saving cache in the flow graph (undo/redo functionality)
STATE_CACHE_SIZE = 42
@@ -90,8 +66,7 @@ CANVAS_GRID_SIZE = 8
# port constraint dimensions
PORT_BORDER_SEPARATION = 8
PORT_SPACING = 2 * PORT_BORDER_SEPARATION
-PORT_SEPARATION = PORT_SPACING + 2 * PORT_LABEL_PADDING + int(1.5 * FONT_SIZE)
-PORT_SEPARATION += -PORT_SEPARATION % (2 * CANVAS_GRID_SIZE) # even multiple
+PORT_SEPARATION = 32
PORT_MIN_WIDTH = 20
PORT_LABEL_HIDDEN_WIDTH = 10
@@ -120,3 +95,17 @@ SCROLL_DISTANCE = 15
# How close the mouse click can be to a line and register a connection select.
LINE_SELECT_SENSITIVITY = 5
+
+
+def update_font_size(font_size):
+ global PORT_SEPARATION, BLOCK_FONT, PORT_FONT, PARAM_FONT, FONT_SIZE
+
+ FONT_SIZE = font_size
+ BLOCK_FONT = "%s %f" % (FONT_FAMILY, font_size)
+ PORT_FONT = BLOCK_FONT
+ PARAM_FONT = "%s %f" % (FONT_FAMILY, font_size - 0.5)
+
+ PORT_SEPARATION = PORT_SPACING + 2 * PORT_LABEL_PADDING + int(1.5 * font_size)
+ PORT_SEPARATION += -PORT_SEPARATION % (2 * CANVAS_GRID_SIZE) # even multiple
+
+update_font_size(DEFAULT_FONT_SIZE)
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
index f2941250a8..6cfdd50a34 100644
--- a/grc/gui/Dialogs.py
+++ b/grc/gui/Dialogs.py
@@ -17,15 +17,13 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import pygtk
-pygtk.require('2.0')
import gtk
import sys
from distutils.spawn import find_executable
-
-from . import Utils, Actions, Constants, Messages
+from . import Utils, Actions
+from ..core import Messages
class SimpleTextDisplay(gtk.TextView):
@@ -177,14 +175,14 @@ def ErrorsDialog(flowgraph): MessageDialogHelper(
class AboutDialog(gtk.AboutDialog):
"""A cute little about dialog."""
- def __init__(self, platform):
+ def __init__(self, config):
"""AboutDialog constructor."""
gtk.AboutDialog.__init__(self)
- self.set_name(platform.get_name())
- self.set_version(platform.get_version())
- self.set_license(platform.get_license())
- self.set_copyright(platform.get_license().splitlines()[0])
- self.set_website(platform.get_website())
+ self.set_name(config.name)
+ self.set_version(config.version)
+ self.set_license(config.license)
+ self.set_copyright(config.license.splitlines()[0])
+ self.set_website(config.website)
self.run()
self.destroy()
@@ -240,7 +238,7 @@ def MissingXTermDialog(xterm):
)
-def ChooseEditorDialog():
+def ChooseEditorDialog(config):
# Give the option to either choose an editor or use the default
# Always return true/false so the caller knows it was successful
buttons = (
@@ -266,10 +264,7 @@ def ChooseEditorDialog():
file_dialog.set_current_folder('/usr/bin')
try:
if file_dialog.run() == gtk.RESPONSE_OK:
- file_path = file_dialog.get_filename()
- Constants.prefs.set_string('grc', 'editor', file_path)
- Constants.prefs.save()
- Constants.EDITOR = file_path
+ config.editor = file_path = file_dialog.get_filename()
file_dialog.destroy()
return file_path
finally:
@@ -287,16 +282,12 @@ def ChooseEditorDialog():
if process is None:
raise ValueError("Can't find default editor executable")
# Save
- Constants.prefs.set_string('grc', 'editor', process)
- Constants.prefs.save()
- Constants.EDITOR = process
+ config.editor = process
return process
except Exception:
Messages.send('>>> Unable to load the default editor. Please choose an editor.\n')
# Just reset of the constant and force the user to select an editor the next time
- Constants.prefs.set_string('grc', 'editor', '')
- Constants.prefs.save()
- Constants.EDITOR = ""
+ config.editor = ''
return
Messages.send('>>> No editor selected.\n')
diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py
index 4412129809..6a1df27a8c 100644
--- a/grc/gui/DrawingArea.py
+++ b/grc/gui/DrawingArea.py
@@ -20,7 +20,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import pygtk
pygtk.require('2.0')
import gtk
+
from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS
+import Colors
+
class DrawingArea(gtk.DrawingArea):
"""
@@ -68,13 +71,21 @@ class DrawingArea(gtk.DrawingArea):
self.set_flags(gtk.CAN_FOCUS) # self.set_can_focus(True)
self.connect('focus-out-event', self._handle_focus_lost_event)
- def new_pixmap(self, width, height): return gtk.gdk.Pixmap(self.window, width, height, -1)
- def get_pixbuf(self):
- width, height = self._pixmap.get_size()
- pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, width, height)
- pixbuf.get_from_drawable(self._pixmap, self._pixmap.get_colormap(), 0, 0, 0, 0, width, height)
+ def new_pixmap(self, width, height):
+ return gtk.gdk.Pixmap(self.window, width, height, -1)
+
+ def get_screenshot(self, transparent_bg=False):
+ pixmap = self._pixmap
+ W, H = pixmap.get_size()
+ pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, W, H)
+ pixbuf.fill(0xFF + Colors.FLOWGRAPH_BACKGROUND_COLOR.pixel << 8)
+ pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, W-1, H-1)
+ if transparent_bg:
+ bgc = Colors.FLOWGRAPH_BACKGROUND_COLOR
+ pixbuf = pixbuf.add_alpha(True, bgc.red, bgc.green, bgc.blue)
return pixbuf
+
##########################################################################
## Handlers
##########################################################################
@@ -149,6 +160,12 @@ class DrawingArea(gtk.DrawingArea):
gc = self.window.new_gc()
self._flow_graph.draw(gc, self._pixmap)
self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1)
+ # draw a light grey line on the bottom and right end of the canvas.
+ # this is useful when the theme uses the same panel bg color as the canvas
+ W, H = self._pixmap.get_size()
+ gc.set_foreground(Colors.FLOWGRAPH_EDGE_COLOR)
+ self.window.draw_line(gc, 0, H-1, W, H-1)
+ self.window.draw_line(gc, W-1, 0, W-1, H)
def _handle_focus_lost_event(self, widget, event):
# don't clear selection while context menu is active
diff --git a/grc/gui/Element.py b/grc/gui/Element.py
index 18fb321929..9385424772 100644
--- a/grc/gui/Element.py
+++ b/grc/gui/Element.py
@@ -132,14 +132,14 @@ class Element(object):
"""
self.coor = coor
- def get_parent(self):
- """
- Get the parent of this element.
-
- Returns:
- the parent
- """
- return self.parent
+ # def get_parent(self):
+ # """
+ # Get the parent of this element.
+ #
+ # Returns:
+ # the parent
+ # """
+ # return self.parent
def set_highlighted(self, highlighted):
"""
diff --git a/grc/gui/Executor.py b/grc/gui/Executor.py
new file mode 100644
index 0000000000..f75f514cdb
--- /dev/null
+++ b/grc/gui/Executor.py
@@ -0,0 +1,123 @@
+# Copyright 2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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 gobject
+import os
+import threading
+import shlex
+import subprocess
+import sys
+import re
+from distutils.spawn import find_executable
+
+from ..core import Messages
+
+
+class ExecFlowGraphThread(threading.Thread):
+ """Execute the flow graph as a new process and wait on it to finish."""
+
+ def __init__(self, action_handler):
+ """
+ ExecFlowGraphThread constructor.
+
+ Args:
+ action_handler: an instance of an ActionHandler
+ """
+ threading.Thread.__init__(self)
+ self.update_exec_stop = action_handler.update_exec_stop
+ self.flow_graph = action_handler.get_flow_graph()
+ self.xterm_executable = action_handler.platform.config.xterm_executable
+ #store page and dont use main window calls in run
+ self.page = action_handler.get_page()
+ #get the popen
+ try:
+ self.p = self._popen()
+ self.page.set_proc(self.p)
+ #update
+ self.update_exec_stop()
+ self.start()
+ except Exception, e:
+ Messages.send_verbose_exec(str(e))
+ Messages.send_end_exec()
+
+ def _popen(self):
+ """
+ Execute this python flow graph.
+ """
+ run_command = self.flow_graph.get_option('run_command')
+ generator = self.page.get_generator()
+
+ try:
+ run_command = run_command.format(
+ python=shlex_quote(sys.executable),
+ filename=shlex_quote(generator.file_path))
+ run_command_args = shlex.split(run_command)
+ except Exception as e:
+ raise ValueError("Can't parse run command {!r}: {}".format(run_command, e))
+
+ # When in no gui mode on linux, use a graphical terminal (looks nice)
+ xterm_executable = find_executable(self.xterm_executable)
+ if generator.generate_options == 'no_gui' and xterm_executable:
+ run_command_args = [xterm_executable, '-e', run_command]
+
+ # this does not reproduce a shell executable command string, if a graphical
+ # terminal is used. Passing run_command though shlex_quote would do it but
+ # it looks really ugly and confusing in the console panel.
+ Messages.send_start_exec(' '.join(run_command_args))
+
+ return subprocess.Popen(
+ args=run_command_args,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ shell=False, universal_newlines=True
+ )
+
+ def run(self):
+ """
+ Wait on the executing process by reading from its stdout.
+ Use gobject.idle_add when calling functions that modify gtk objects.
+ """
+ #handle completion
+ r = "\n"
+ while r:
+ gobject.idle_add(Messages.send_verbose_exec, r)
+ r = os.read(self.p.stdout.fileno(), 1024)
+ self.p.poll()
+ gobject.idle_add(self.done)
+
+ def done(self):
+ """Perform end of execution tasks."""
+ Messages.send_end_exec(self.p.returncode)
+ self.page.set_proc(None)
+ self.update_exec_stop()
+
+
+###########################################################
+# back-port from python3
+###########################################################
+_find_unsafe = re.compile(r'[^\w@%+=:,./-]').search
+
+
+def shlex_quote(s):
+ """Return a shell-escaped version of the string *s*."""
+ if not s:
+ return "''"
+ if _find_unsafe(s) is None:
+ return s
+
+ # use single quotes, and put single quotes into double quotes
+ # the string $'b is then quoted as '$'"'"'b'
+ return "'" + s.replace("'", "'\"'\"'") + "'"
diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py
index 730ac6fba0..4b5770ad21 100644
--- a/grc/gui/FileDialogs.py
+++ b/grc/gui/FileDialogs.py
@@ -210,3 +210,18 @@ class SaveFlowGraphFileDialog(FileDialog): type = SAVE_FLOW_GRAPH
class OpenQSSFileDialog(FileDialog): type = OPEN_QSS_THEME
class SaveReportsFileDialog(FileDialog): type = SAVE_REPORTS
class SaveImageFileDialog(FileDialog): type = SAVE_IMAGE
+
+
+class SaveScreenShotDialog(SaveImageFileDialog):
+
+ def __init__(self, current_file_path=''):
+ SaveImageFileDialog.__init__(self, current_file_path)
+ self._button = button = gtk.CheckButton('_Background transparent')
+ self._button.set_active(Preferences.screen_shot_background_transparent())
+ self.set_extra_widget(button)
+
+ def run(self):
+ filename = SaveImageFileDialog.run(self)
+ bg_transparent = self._button.get_active()
+ Preferences.screen_shot_background_transparent(bg_transparent)
+ return filename, bg_transparent
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 2053e86454..357f87c894 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -17,39 +17,43 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-import random
import functools
-from itertools import chain
-from operator import methodcaller
+import random
from distutils.spawn import find_executable
+from itertools import chain, count
+from operator import methodcaller
import gobject
-from . import Actions, Colors, Constants, Utils, Messages, Bars, Dialogs
-from . Element import Element
-from . Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
-from . external_editor import ExternalEditor
+from . import Actions, Colors, Constants, Utils, Bars, Dialogs
+from .Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
+from .Element import Element
+from .external_editor import ExternalEditor
+from ..core.FlowGraph import FlowGraph as _Flowgraph
+from ..core import Messages
-class FlowGraph(Element):
+
+class FlowGraph(Element, _Flowgraph):
"""
FlowGraph is the data structure to store graphical signal blocks,
graphical inputs and outputs,
and the connections between inputs and outputs.
"""
- def __init__(self):
+ def __init__(self, **kwargs):
"""
FlowGraph constructor.
Create a list for signal blocks and connections. Connect mouse handlers.
"""
Element.__init__(self)
+ _Flowgraph.__init__(self, **kwargs)
#when is the flow graph selected? (used by keyboard event handler)
self.is_selected = lambda: bool(self.get_selected_elements())
#important vars dealing with mouse event tracking
self.element_moved = False
self.mouse_pressed = False
- self.unselect()
+ self._selected_elements = []
self.press_coor = (0, 0)
#selected ports
self._old_selected_port = None
@@ -62,14 +66,31 @@ class FlowGraph(Element):
self._external_updaters = {}
+ def _get_unique_id(self, base_id=''):
+ """
+ Get a unique id starting with the base id.
+
+ Args:
+ base_id: the id starts with this and appends a count
+
+ Returns:
+ a unique id
+ """
+ for index in count():
+ block_id = '{}_{}'.format(base_id, index)
+ if block_id not in (b.get_id() for b in self.blocks):
+ break
+ return block_id
+
def install_external_editor(self, param):
target = (param.get_parent().get_id(), param.get_key())
if target in self._external_updaters:
editor = self._external_updaters[target]
else:
- editor = (find_executable(Constants.EDITOR) or
- Dialogs.ChooseEditorDialog())
+ config = self.get_parent().config
+ editor = (find_executable(config.editor) or
+ Dialogs.ChooseEditorDialog(config))
if not editor:
return
updater = functools.partial(
@@ -86,9 +107,7 @@ class FlowGraph(Element):
# Problem launching the editor. Need to select a new editor.
Messages.send('>>> Error opening an external editor. Please select a different editor.\n')
# Reset the editor to force the user to select a new one.
- Constants.prefs.set_string('grc', 'editor', '')
- Constants.prefs.save()
- Constants.EDITOR = ""
+ self.get_parent().config.editor = ''
def handle_external_editor_change(self, new_value, target):
try:
@@ -131,7 +150,7 @@ class FlowGraph(Element):
int(random.uniform(.25, .75)*v_adj.page_size + v_adj.get_value()),
)
#get the new block
- block = self.get_new_block(key)
+ block = self.new_block(key)
block.set_coordinate(coor)
block.set_rotation(0)
block.get_param('id').set_value(id)
@@ -160,7 +179,7 @@ class FlowGraph(Element):
#get connections between selected blocks
connections = filter(
lambda c: c.get_source().get_parent() in blocks and c.get_sink().get_parent() in blocks,
- self.get_connections(),
+ self.connections,
)
clipboard = (
(x_min, y_min),
@@ -190,7 +209,7 @@ class FlowGraph(Element):
for block_n in blocks_n:
block_key = block_n.find('key')
if block_key == 'options': continue
- block = self.get_new_block(block_key)
+ block = self.new_block(block_key)
if not block:
continue # unknown block was pasted (e.g. dummy block)
selected.add(block)
@@ -206,7 +225,7 @@ class FlowGraph(Element):
if param_key == 'id':
old_id2block[param_value] = block
#if the block id is not unique, get a new block id
- if param_value in [blk.get_id() for blk in self.get_blocks()]:
+ if param_value in (blk.get_id() for blk in self.blocks):
param_value = self._get_unique_id(param_value)
#set value to key
block.get_param(param_key).set_value(param_value)
@@ -350,7 +369,7 @@ class FlowGraph(Element):
# draw comments first
if Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active():
- for block in self.iter_blocks():
+ for block in self.blocks:
if block.get_enabled():
block.draw_comment(gc, window)
#draw multi select rectangle
@@ -368,8 +387,8 @@ class FlowGraph(Element):
window.draw_rectangle(gc, False, x, y, w, h)
#draw blocks on top of connections
hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active()
- blocks = sorted(self.iter_blocks(), key=methodcaller('get_enabled'))
- for element in chain(self.iter_connections(), blocks):
+ blocks = sorted(self.blocks, key=methodcaller('get_enabled'))
+ for element in chain(self.connections, blocks):
if hide_disabled_blocks and not element.get_enabled():
continue # skip hidden disabled blocks and connections
element.draw(gc, window)
@@ -432,6 +451,10 @@ class FlowGraph(Element):
"""
self._selected_elements = []
+ def select_all(self):
+ """Select all blocks in the flow graph"""
+ self._selected_elements = list(self.get_elements())
+
def what_is_selected(self, coor, coor_m=None):
"""
What is selected?
@@ -456,13 +479,13 @@ class FlowGraph(Element):
if not selected_element: continue
# hidden disabled connections, blocks and their ports can not be selected
if Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active() and (
- selected_element.is_block() and not selected_element.get_enabled() or
- selected_element.is_connection() and not selected_element.get_enabled() or
- selected_element.is_port() and not selected_element.get_parent().get_enabled()
+ selected_element.is_block and not selected_element.get_enabled() or
+ selected_element.is_connection and not selected_element.get_enabled() or
+ selected_element.is_port and not selected_element.get_parent().get_enabled()
):
continue
#update the selected port information
- if selected_element.is_port():
+ if selected_element.is_port:
if not coor_m: selected_port = selected_element
selected_element = selected_element.get_parent()
selected.add(selected_element)
@@ -486,7 +509,8 @@ class FlowGraph(Element):
"""
selected = set()
for selected_element in self.get_selected_elements():
- if selected_element.is_connection(): selected.add(selected_element)
+ if selected_element.is_connection:
+ selected.add(selected_element)
return list(selected)
def get_selected_blocks(self):
@@ -498,7 +522,8 @@ class FlowGraph(Element):
"""
selected = set()
for selected_element in self.get_selected_elements():
- if selected_element.is_block(): selected.add(selected_element)
+ if selected_element.is_block:
+ selected.add(selected_element)
return list(selected)
def get_selected_block(self):
@@ -673,7 +698,7 @@ class FlowGraph(Element):
adj.set_value(adj_val-SCROLL_DISTANCE)
adj.emit('changed')
#remove the connection if selected in drag event
- if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection():
+ if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection:
Actions.ELEMENT_DELETE()
#move the selected elements and record the new coordinate
if not self.get_ctrl_mask():
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
index a340bcc817..6da240d85b 100644
--- a/grc/gui/MainWindow.py
+++ b/grc/gui/MainWindow.py
@@ -17,21 +17,19 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from Constants import \
- NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH
-import Actions
-import pygtk
-pygtk.require('2.0')
-import gtk
-import Bars
-from BlockTreeWindow import BlockTreeWindow
-from Dialogs import TextDisplay, MessageDialogHelper
-from NotebookPage import NotebookPage
-import Preferences
-import Messages
-import Utils
import os
+import gtk
+
+from . import Bars, Actions, Preferences, Utils
+from .BlockTreeWindow import BlockTreeWindow
+from .Constants import \
+ NEW_FLOGRAPH_TITLE, DEFAULT_REPORTS_WINDOW_WIDTH
+from .Dialogs import TextDisplay, MessageDialogHelper
+from .NotebookPage import NotebookPage
+
+from ..core import Messages
+
MAIN_WINDOW_TITLE_TMPL = """\
#if not $saved
*#slurp
@@ -71,11 +69,13 @@ class MainWindow(gtk.Window):
Setup the menu, toolbar, flowgraph editor notebook, block selection window...
"""
self._platform = platform
- gen_opts = platform.get_block('options').get_param('generate_options')
+
+ gen_opts = platform.blocks['options'].get_param('generate_options')
generate_mode_default = gen_opts.get_value()
generate_modes = [
(o.get_key(), o.get_name(), o.get_key() == generate_mode_default)
for o in gen_opts.get_options()]
+
# load preferences
Preferences.load(platform)
#setup window
@@ -283,7 +283,7 @@ class MainWindow(gtk.Window):
new_flowgraph_title=NEW_FLOGRAPH_TITLE,
read_only=self.get_page().get_read_only(),
saved=self.get_page().get_saved(),
- platform_name=self._platform.get_name(),
+ platform_name=self._platform.config.name,
)
)
#set tab titles
diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py
index 4c112154af..6614649c89 100644
--- a/grc/gui/NotebookPage.py
+++ b/grc/gui/NotebookPage.py
@@ -102,10 +102,8 @@ class NotebookPage(gtk.HBox):
Returns:
generator
"""
- return self.get_flow_graph().get_parent().get_generator()(
- self.get_flow_graph(),
- self.get_file_path(),
- )
+ platform = self.get_flow_graph().get_parent()
+ return platform.Generator(self.get_flow_graph(), self.get_file_path())
def _handle_button(self, button):
"""
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index 6884d6530a..bf0a59b96b 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -23,8 +23,10 @@ import pygtk
pygtk.require('2.0')
import gtk
-from . import Colors, Utils, Constants, Dialogs
-from . Element import Element
+from . import Colors, Utils, Constants
+from .Element import Element
+
+from ..core.Param import Param as _Param
class InputParam(gtk.HBox):
@@ -317,7 +319,9 @@ class FileParam(EntryParam):
if self.param.get_key() == 'qt_qss_theme':
dirname = os.path.dirname(dirname) # trim filename
if not os.path.exists(dirname):
- dirname = os.path.join(Constants.GR_PREFIX, '/share/gnuradio/themes')
+ platform = self.param.get_parent().get_parent().get_parent()
+ dirname = os.path.join(platform.config.install_prefix,
+ '/share/gnuradio/themes')
if not os.path.exists(dirname):
dirname = os.getcwd() # fix bad paths
@@ -378,11 +382,12 @@ Error:
#end if"""
-class Param(Element):
+class Param(Element, _Param):
"""The graphical parameter."""
- def __init__(self):
+ def __init__(self, **kwargs):
Element.__init__(self)
+ _Param.__init__(self, **kwargs)
def get_input(self, *args, **kwargs):
"""
diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py
index eda28a0e94..500df1cce4 100644
--- a/grc/gui/Platform.py
+++ b/grc/gui/Platform.py
@@ -17,12 +17,55 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from Element import Element
+import os
+import sys
-class Platform(Element):
- def __init__(self, prefs_file):
+from ..core.Platform import Platform as _Platform
+
+from .Config import Config as _Config
+from .Block import Block as _Block
+from .Connection import Connection as _Connection
+from .Element import Element
+from .FlowGraph import FlowGraph as _FlowGraph
+from .Param import Param as _Param
+from .Port import Port as _Port
+
+
+class Platform(Element, _Platform):
+
+ def __init__(self, *args, **kwargs):
Element.__init__(self)
+ _Platform.__init__(self, *args, **kwargs)
+
+ # Ensure conf directories
+ gui_prefs_file = self.config.gui_prefs_file
+ if not os.path.exists(os.path.dirname(gui_prefs_file)):
+ os.mkdir(os.path.dirname(gui_prefs_file))
+
+ self._move_old_pref_file()
+
+ def get_prefs_file(self):
+ return self.config.gui_prefs_file
- self._prefs_file = prefs_file
+ def _move_old_pref_file(self):
+ gui_prefs_file = self.config.gui_prefs_file
+ old_gui_prefs_file = os.environ.get(
+ 'GRC_PREFS_PATH', os.path.expanduser('~/.grc'))
+ if gui_prefs_file == old_gui_prefs_file:
+ return # prefs file overridden with env var
+ if os.path.exists(old_gui_prefs_file) and not os.path.exists(gui_prefs_file):
+ try:
+ import shutil
+ shutil.move(old_gui_prefs_file, gui_prefs_file)
+ except Exception as e:
+ print >> sys.stderr, e
- def get_prefs_file(self): return self._prefs_file
+ ##############################################
+ # Constructors
+ ##############################################
+ FlowGraph = _FlowGraph
+ Connection = _Connection
+ Block = _Block
+ Port = _Port
+ Param = _Param
+ Config = _Config
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index ae1a1d223f..6314b7ede8 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -17,32 +17,33 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
"""
-from Element import Element
-from Constants import (
- PORT_SEPARATION, PORT_SPACING, CONNECTOR_EXTENSION_MINIMAL,
- CONNECTOR_EXTENSION_INCREMENT, CANVAS_GRID_SIZE,
- PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT
-)
-from .. base.Constants import DEFAULT_DOMAIN, GR_MESSAGE_DOMAIN
-import Utils
-import Actions
-import Colors
import pygtk
pygtk.require('2.0')
import gtk
+from . import Actions, Colors, Utils
+from .Constants import (
+ PORT_SEPARATION, PORT_SPACING, CONNECTOR_EXTENSION_MINIMAL,
+ CONNECTOR_EXTENSION_INCREMENT, PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT
+)
+from .Element import Element
+from ..core.Constants import DEFAULT_DOMAIN, GR_MESSAGE_DOMAIN
+
+from ..core.Port import Port as _Port
+
PORT_MARKUP_TMPL="""\
<span foreground="black" font_desc="$font">$encode($port.get_name())</span>"""
-class Port(Element):
+class Port(_Port, Element):
"""The graphical port."""
- def __init__(self):
+ def __init__(self, block, n, dir):
"""
Port contructor.
Create list of connector coordinates.
"""
+ _Port.__init__(self, block, n, dir)
Element.__init__(self)
self.W = self.H = self.w = self.h = 0
self._connector_coordinate = (0, 0)
@@ -63,7 +64,7 @@ class Port(Element):
rotation = self.get_rotation()
#get all sibling ports
ports = self.get_parent().get_sources_gui() \
- if self.is_source() else self.get_parent().get_sinks_gui()
+ if self.is_source else self.get_parent().get_sinks_gui()
ports = filter(lambda p: not p.get_hide(), ports)
#get the max width
self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH])
@@ -81,27 +82,27 @@ class Port(Element):
index = length-index-1
port_separation = PORT_SEPARATION \
- if not self.get_parent().has_busses[self.is_source()] \
+ if not self.get_parent().has_busses[self.is_source] \
else max([port.H for port in ports]) + PORT_SPACING
offset = (self.get_parent().H - (length-1)*port_separation - self.H)/2
#create areas and connector coordinates
- if (self.is_sink() and rotation == 0) or (self.is_source() and rotation == 180):
+ if (self.is_sink and rotation == 0) or (self.is_source and rotation == 180):
x = -W
y = port_separation*index+offset
self.add_area((x, y), (W, self.H))
self._connector_coordinate = (x-1, y+self.H/2)
- elif (self.is_source() and rotation == 0) or (self.is_sink() and rotation == 180):
+ elif (self.is_source and rotation == 0) or (self.is_sink and rotation == 180):
x = self.get_parent().W
y = port_separation*index+offset
self.add_area((x, y), (W, self.H))
self._connector_coordinate = (x+1+W, y+self.H/2)
- elif (self.is_source() and rotation == 90) or (self.is_sink() and rotation == 270):
+ elif (self.is_source and rotation == 90) or (self.is_sink and rotation == 270):
y = -W
x = port_separation*index+offset
self.add_area((x, y), (self.H, W))
self._connector_coordinate = (x+self.H/2, y-1)
- elif (self.is_sink() and rotation == 90) or (self.is_source() and rotation == 270):
+ elif (self.is_sink and rotation == 90) or (self.is_source and rotation == 270):
y = self.get_parent().W
x = port_separation*index+offset
self.add_area((x, y), (self.H, W))
@@ -144,7 +145,7 @@ class Port(Element):
Element.draw(
self, gc, window, bg_color=self._bg_color,
border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or
- self.get_parent().is_dummy_block() and Colors.MISSING_BLOCK_BORDER_COLOR or
+ self.get_parent().is_dummy_block and Colors.MISSING_BLOCK_BORDER_COLOR or
Colors.BORDER_COLOR,
)
if not self._areas_list or self._label_hidden():
@@ -176,8 +177,8 @@ class Port(Element):
Returns:
the direction in degrees
"""
- if self.is_source(): return self.get_rotation()
- elif self.is_sink(): return (self.get_rotation() + 180)%360
+ if self.is_source: return self.get_rotation()
+ elif self.is_sink: return (self.get_rotation() + 180)%360
def get_connector_length(self):
"""
diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py
index 3ebee24345..1a194fd8c5 100644
--- a/grc/gui/Preferences.py
+++ b/grc/gui/Preferences.py
@@ -35,7 +35,7 @@ _config_parser = ConfigParser.SafeConfigParser()
def file_extension():
- return '.'+_platform.get_key()
+ return '.grc'
def load(platform):
@@ -150,3 +150,7 @@ def blocks_window_position(pos=None):
def xterm_missing(cmd=None):
return entry('xterm_missing', cmd, default='INVALID_XTERM_SETTING')
+
+
+def screen_shot_background_transparent(transparent=None):
+ return entry('screen_shot_background_transparent', transparent, default=False)
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
index bf7d31d391..7c66a77a54 100644
--- a/grc/gui/PropsDialog.py
+++ b/grc/gui/PropsDialog.py
@@ -97,7 +97,8 @@ class PropsDialog(gtk.Dialog):
self._params_boxes.append((tab, label, vbox))
# Docs for the block
- self._docs_text_display = SimpleTextDisplay()
+ self._docs_text_display = doc_view = SimpleTextDisplay()
+ doc_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD)
self._docs_box = gtk.ScrolledWindow()
self._docs_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self._docs_box.add_with_viewport(self._docs_text_display)
@@ -200,10 +201,43 @@ class PropsDialog(gtk.Dialog):
messages = '\n\n'.join(self._block.get_error_messages())
self._error_messages_text_display.set_text(messages)
# update the docs box
- self._docs_text_display.set_text(self._block.get_doc())
+ self._update_docs_page()
# update the generated code
self._update_generated_code_page()
+ def _update_docs_page(self):
+ """Show documentation from XML and try to display best matching docstring"""
+ buffer = self._docs_text_display.get_buffer()
+ buffer.delete(buffer.get_start_iter(), buffer.get_end_iter())
+ pos = buffer.get_end_iter()
+
+ docstrings = self._block.get_doc()
+ if not docstrings:
+ return
+
+ # show documentation string from block xml
+ from_xml = docstrings.pop('', '')
+ for line in from_xml.splitlines():
+ if line.lstrip() == line and line.endswith(':'):
+ buffer.insert_with_tags_by_name(pos, line + '\n', 'b')
+ else:
+ buffer.insert(pos, line + '\n')
+ if from_xml:
+ buffer.insert(pos, '\n')
+
+ # if given the current parameters an exact match can be made
+ block_constructor = self._block.get_make().rsplit('.', 2)[-1]
+ block_class = block_constructor.partition('(')[0].strip()
+ if block_class in docstrings:
+ docstrings = {block_class: docstrings[block_class]}
+
+ # show docstring(s) extracted from python sources
+ for cls_name, docstring in docstrings.iteritems():
+ buffer.insert_with_tags_by_name(pos, cls_name + '\n', 'b')
+ buffer.insert(pos, docstring + '\n\n')
+ pos.backward_chars(2)
+ buffer.delete(pos, buffer.get_end_iter())
+
def _update_generated_code_page(self):
if not self._code_text_display:
return # user disabled code preview
diff --git a/grc/main.py b/grc/main.py
new file mode 100755
index 0000000000..ae7a0ce115
--- /dev/null
+++ b/grc/main.py
@@ -0,0 +1,55 @@
+# Copyright 2009-2016 Free Software Foundation, Inc.
+# This file is part of GNU Radio
+#
+# GNU Radio Companion 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 2
+# of the License, or (at your option) any later version.
+#
+# GNU Radio Companion 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 optparse
+
+import gtk
+from gnuradio import gr
+
+from .gui.Platform import Platform
+from .gui.ActionHandler import ActionHandler
+
+
+VERSION_AND_DISCLAIMER_TEMPLATE = """\
+GNU Radio Companion %s
+
+This program is part of GNU Radio
+GRC comes with ABSOLUTELY NO WARRANTY.
+This is free software, and you are welcome to redistribute it.
+"""
+
+
+def main():
+ parser = optparse.OptionParser(
+ usage='usage: %prog [options] [saved flow graphs]',
+ version=VERSION_AND_DISCLAIMER_TEMPLATE % gr.version())
+ options, args = parser.parse_args()
+
+ try:
+ gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0))
+ except:
+ pass
+
+ platform = Platform(
+ prefs_file=gr.prefs(),
+ version=gr.version(),
+ version_parts=(gr.major_version(), gr.api_version(), gr.minor_version()),
+ install_prefix=gr.prefix()
+ )
+ ActionHandler(args, platform)
+ gtk.main()
+
diff --git a/grc/python/Block.py b/grc/python/Block.py
deleted file mode 100644
index 782893fd8f..0000000000
--- a/grc/python/Block.py
+++ /dev/null
@@ -1,323 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 itertools
-import collections
-
-from .. base.Constants import BLOCK_FLAG_NEED_QT_GUI, BLOCK_FLAG_NEED_WX_GUI
-from .. base.odict import odict
-
-from .. base.Block import Block as _Block
-from .. gui.Block import Block as _GUIBlock
-
-from . FlowGraph import _variable_matcher
-from . import epy_block_io
-
-
-class Block(_Block, _GUIBlock):
-
- def __init__(self, flow_graph, n):
- """
- Make a new block from nested data.
-
- Args:
- flow: graph the parent element
- n: the nested odict
-
- Returns:
- block a new block
- """
- #grab the data
- self._doc = (n.find('doc') or '').strip('\n').replace('\\\n', '')
- self._imports = map(lambda i: i.strip(), n.findall('import'))
- self._make = n.find('make')
- self._var_make = n.find('var_make')
- self._checks = n.findall('check')
- self._callbacks = n.findall('callback')
- self._bus_structure_source = n.find('bus_structure_source') or ''
- self._bus_structure_sink = n.find('bus_structure_sink') or ''
- self.port_counters = [itertools.count(), itertools.count()]
- #build the block
- _Block.__init__(
- self,
- flow_graph=flow_graph,
- n=n,
- )
- _GUIBlock.__init__(self)
-
- self._epy_source_hash = -1 # for epy blocks
- self._epy_reload_error = None
-
- def get_bus_structure(self, direction):
- if direction == 'source':
- bus_structure = self._bus_structure_source;
- else:
- bus_structure = self._bus_structure_sink;
-
- bus_structure = self.resolve_dependencies(bus_structure);
-
- if not bus_structure: return ''
- try:
- clean_bus_structure = self.get_parent().evaluate(bus_structure)
- return clean_bus_structure
-
- except: return ''
-
- def validate(self):
- """
- Validate this block.
- Call the base class validate.
- Evaluate the checks: each check must evaluate to True.
- """
- _Block.validate(self)
- #evaluate the checks
- for check in self._checks:
- check_res = self.resolve_dependencies(check)
- try:
- if not self.get_parent().evaluate(check_res):
- self.add_error_message('Check "%s" failed.'%check)
- except: self.add_error_message('Check "%s" did not evaluate.'%check)
- # for variables check the value (only if var_value is used
- if _variable_matcher.match(self.get_key()) and self._var_value != '$value':
- value = self._var_value
- try:
- value = self.get_var_value()
- self.get_parent().evaluate(value)
- except Exception as err:
- self.add_error_message('Value "%s" cannot be evaluated:\n%s' % (value, err))
-
- # check if this is a GUI block and matches the selected generate option
- current_generate_option = self.get_parent().get_option('generate_options')
-
- def check_generate_mode(label, flag, valid_options):
- block_requires_mode = (
- flag in self.get_flags() or
- self.get_name().upper().startswith(label)
- )
- if block_requires_mode and current_generate_option not in valid_options:
- self.add_error_message("Can't generate this block in mode " +
- repr(current_generate_option))
-
- check_generate_mode('WX GUI', BLOCK_FLAG_NEED_WX_GUI, ('wx_gui',))
- check_generate_mode('QT GUI', BLOCK_FLAG_NEED_QT_GUI, ('qt_gui', 'hb_qt_gui'))
- if self._epy_reload_error:
- self.get_param('_source_code').add_error_message(str(self._epy_reload_error))
-
- def rewrite(self):
- """
- Add and remove ports to adjust for the nports.
- """
- _Block.rewrite(self)
- # Check and run any custom rewrite function for this block
- getattr(self, 'rewrite_' + self._key, lambda: None)()
-
- # adjust nports, disconnect hidden ports
- for ports in (self.get_sources(), self.get_sinks()):
- for i, master_port in enumerate(ports):
- nports = master_port.get_nports() or 1
- num_ports = 1 + len(master_port.get_clones())
- if master_port.get_hide():
- for connection in master_port.get_connections():
- self.get_parent().remove_element(connection)
- if not nports and num_ports == 1: # not a master port and no left-over clones
- continue
- # remove excess cloned ports
- for port in master_port.get_clones()[nports-1:]:
- # remove excess connections
- for connection in port.get_connections():
- self.get_parent().remove_element(connection)
- master_port.remove_clone(port)
- ports.remove(port)
- # add more cloned ports
- for j in range(num_ports, nports):
- port = master_port.add_clone()
- ports.insert(ports.index(master_port) + j, port)
-
- self.back_ofthe_bus(ports)
- # renumber non-message/-msg ports
- domain_specific_port_index = collections.defaultdict(int)
- for port in filter(lambda p: p.get_key().isdigit(), ports):
- domain = port.get_domain()
- port._key = str(domain_specific_port_index[domain])
- domain_specific_port_index[domain] += 1
-
- def port_controller_modify(self, direction):
- """
- Change the port controller.
-
- Args:
- direction: +1 or -1
-
- Returns:
- true for change
- """
- changed = False
- #concat the nports string from the private nports settings of all ports
- nports_str = ' '.join([port._nports for port in self.get_ports()])
- #modify all params whose keys appear in the nports string
- for param in self.get_params():
- if param.is_enum() or param.get_key() not in nports_str: continue
- #try to increment the port controller by direction
- try:
- value = param.get_evaluated()
- value = value + direction
- if 0 < value:
- param.set_value(value)
- changed = True
- except: pass
- return changed
-
- def get_doc(self):
- platform = self.get_parent().get_parent()
- extracted_docs = platform.block_docstrings.get(self._key, '')
- return (self._doc + '\n\n' + extracted_docs).strip()
-
- def get_category(self):
- return _Block.get_category(self)
-
- def get_imports(self, raw=False):
- """
- Resolve all import statements.
- Split each import statement at newlines.
- Combine all import statments into a list.
- Filter empty imports.
-
- Returns:
- a list of import statements
- """
- if raw:
- return self._imports
- return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), []))
-
- def get_make(self, raw=False):
- if raw:
- return self._make
- return self.resolve_dependencies(self._make)
-
- def get_var_make(self):
- return self.resolve_dependencies(self._var_make)
-
- def get_var_value(self):
- return self.resolve_dependencies(self._var_value)
-
- def get_callbacks(self):
- """
- Get a list of function callbacks for this block.
-
- Returns:
- a list of strings
- """
- def make_callback(callback):
- callback = self.resolve_dependencies(callback)
- if 'self.' in callback: return callback
- return 'self.%s.%s'%(self.get_id(), callback)
- return map(make_callback, self._callbacks)
-
- def is_virtual_sink(self):
- return self.get_key() == 'virtual_sink'
-
- def is_virtual_source(self):
- return self.get_key() == 'virtual_source'
-
- ###########################################################################
- # Custom rewrite functions
- ###########################################################################
-
- def rewrite_epy_block(self):
- flowgraph = self.get_parent()
- platform = flowgraph.get_parent()
- param_blk = self.get_param('_io_cache')
- param_src = self.get_param('_source_code')
- doc_end_tag = 'Block Documentation:'
-
- src = param_src.get_value()
- src_hash = hash((self.get_id(), src))
- if src_hash == self._epy_source_hash:
- return
-
- try:
- blk_io = epy_block_io.extract(src)
-
- except Exception as e:
- self._epy_reload_error = ValueError(str(e))
- try: # load last working block io
- blk_io = epy_block_io.BlockIO(*eval(param_blk.get_value()))
- except:
- return
- else:
- self._epy_reload_error = None # clear previous errors
- param_blk.set_value(repr(tuple(blk_io)))
-
- # print "Rewriting embedded python block {!r}".format(self.get_id())
- self._epy_source_hash = src_hash
- self._name = blk_io.name or blk_io.cls
- self._doc = self._doc.split(doc_end_tag)[0] + doc_end_tag + '\n' + blk_io.doc
- self._imports[0] = 'import ' + self.get_id()
- self._make = '{0}.{1}({2})'.format(self.get_id(), blk_io.cls, ', '.join(
- '{0}=${0}'.format(key) for key, _ in blk_io.params))
-
- params = {}
- for param in list(self._params):
- if hasattr(param, '__epy_param__'):
- params[param.get_key()] = param
- self._params.remove(param)
-
- for key, value in blk_io.params:
- try:
- param = params[key]
- param.set_default(value)
- except KeyError: # need to make a new param
- name = key.replace('_', ' ').title()
- n = odict(dict(name=name, key=key, type='raw', value=value))
- param = platform.Param(block=self, n=n)
- setattr(param, '__epy_param__', True)
- self._params.append(param)
-
- def update_ports(label, ports, port_specs, direction):
- ports_to_remove = list(ports)
- iter_ports = iter(ports)
- ports_new = []
- port_current = next(iter_ports, None)
- for key, port_type in port_specs:
- reuse_port = (
- port_current is not None and
- port_current.get_type() == port_type and
- (key.isdigit() or port_current.get_key() == key)
- )
- if reuse_port:
- ports_to_remove.remove(port_current)
- port, port_current = port_current, next(iter_ports, None)
- else:
- n = odict(dict(name=label + str(key), type=port_type, key=key))
- if port_type == 'message':
- n['name'] = key
- n['optional'] = '1'
- port = platform.Port(block=self, n=n, dir=direction)
- ports_new.append(port)
- # replace old port list with new one
- del ports[:]
- ports.extend(ports_new)
- # remove excess port connections
- for port in ports_to_remove:
- for connection in port.get_connections():
- flowgraph.remove_element(connection)
-
- update_ports('in', self.get_sinks(), blk_io.sinks, 'sink')
- update_ports('out', self.get_sources(), blk_io.sources, 'source')
- _Block.rewrite(self)
diff --git a/grc/python/Connection.py b/grc/python/Connection.py
deleted file mode 100644
index 822876a0ae..0000000000
--- a/grc/python/Connection.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 Constants
-from .. base.Connection import Connection as _Connection
-from .. gui.Connection import Connection as _GUIConnection
-
-class Connection(_Connection, _GUIConnection):
-
- def __init__(self, **kwargs):
- _Connection.__init__(self, **kwargs)
- _GUIConnection.__init__(self)
-
- def is_msg(self):
- return self.get_source().get_type() == self.get_sink().get_type() == 'msg'
-
- def is_bus(self):
- return self.get_source().get_type() == self.get_sink().get_type() == 'bus'
-
- def validate(self):
- """
- Validate the connections.
- The ports must match in io size.
- """
- _Connection.validate(self)
- source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen()
- sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen()
- if source_size != sink_size:
- self.add_error_message('Source IO size "%s" does not match sink IO size "%s".'%(source_size, sink_size))
diff --git a/grc/python/FlowGraph.py b/grc/python/FlowGraph.py
deleted file mode 100644
index b2a1d27859..0000000000
--- a/grc/python/FlowGraph.py
+++ /dev/null
@@ -1,338 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 re
-import imp
-from operator import methodcaller
-
-from . import expr_utils
-from .. base.FlowGraph import FlowGraph as _FlowGraph
-from .. gui.FlowGraph import FlowGraph as _GUIFlowGraph
-
-_variable_matcher = re.compile('^(variable\w*)$')
-_parameter_matcher = re.compile('^(parameter)$')
-_monitors_searcher = re.compile('(ctrlport_monitor)')
-_bussink_searcher = re.compile('^(bus_sink)$')
-_bussrc_searcher = re.compile('^(bus_source)$')
-_bus_struct_sink_searcher = re.compile('^(bus_structure_sink)$')
-_bus_struct_src_searcher = re.compile('^(bus_structure_source)$')
-
-
-class FlowGraph(_FlowGraph, _GUIFlowGraph):
-
- def __init__(self, **kwargs):
- self.grc_file_path = ''
- _FlowGraph.__init__(self, **kwargs)
- _GUIFlowGraph.__init__(self)
- self.n = {}
- self.n_hash = -1
- self._renew_eval_ns = True
- self._eval_cache = {}
-
- def _eval(self, code, namespace, namespace_hash):
- """
- Evaluate the code with the given namespace.
-
- Args:
- code: a string with python code
- namespace: a dict representing the namespace
- namespace_hash: a unique hash for the namespace
-
- Returns:
- the resultant object
- """
- if not code: raise Exception, 'Cannot evaluate empty statement.'
- my_hash = hash(code) ^ namespace_hash
- #cache if does not exist
- if not self._eval_cache.has_key(my_hash):
- self._eval_cache[my_hash] = eval(code, namespace, namespace)
- #return from cache
- return self._eval_cache[my_hash]
-
- def get_hier_block_stream_io(self, direction):
- """
- Get a list of stream io signatures for this flow graph.
-
- Args:
- direction: a string of 'in' or 'out'
-
- Returns:
- a list of dicts with: type, label, vlen, size, optional
- """
- return filter(lambda p: p['type'] != "message",
- self.get_hier_block_io(direction))
-
- def get_hier_block_message_io(self, direction):
- """
- Get a list of message io signatures for this flow graph.
-
- Args:
- direction: a string of 'in' or 'out'
-
- Returns:
- a list of dicts with: type, label, vlen, size, optional
- """
- return filter(lambda p: p['type'] == "message",
- self.get_hier_block_io(direction))
-
- def get_hier_block_io(self, direction):
- """
- Get a list of io ports for this flow graph.
-
- Args:
- direction: a string of 'in' or 'out'
-
- Returns:
- a list of dicts with: type, label, vlen, size, optional
- """
- pads = self.get_pad_sources() if direction in ('sink', 'in') else \
- self.get_pad_sinks() if direction in ('source', 'out') else []
- ports = []
- for pad in pads:
- master = {
- 'label': str(pad.get_param('label').get_evaluated()),
- 'type': str(pad.get_param('type').get_evaluated()),
- 'vlen': str(pad.get_param('vlen').get_value()),
- 'size': pad.get_param('type').get_opt('size'),
- 'optional': bool(pad.get_param('optional').get_evaluated()),
- }
- num_ports = pad.get_param('num_streams').get_evaluated()
- if num_ports > 1:
- for i in xrange(num_ports):
- clone = master.copy()
- clone['label'] += str(i)
- ports.append(clone)
- else:
- ports.append(master)
- return ports
-
- def get_pad_sources(self):
- """
- Get a list of pad source blocks sorted by id order.
-
- Returns:
- a list of pad source blocks in this flow graph
- """
- pads = filter(lambda b: b.get_key() == 'pad_source', self.get_enabled_blocks())
- return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
-
- def get_pad_sinks(self):
- """
- Get a list of pad sink blocks sorted by id order.
-
- Returns:
- a list of pad sink blocks in this flow graph
- """
- pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks())
- return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id()))
-
- def get_pad_port_global_key(self, port):
- """
- Get the key for a port of a pad source/sink to use in connect()
- This takes into account that pad blocks may have multiple ports
-
- Returns:
- the key (str)
- """
- key_offset = 0
- pads = self.get_pad_sources() if port.is_source() else self.get_pad_sinks()
- for pad in pads:
- # using the block param 'type' instead of the port domain here
- # to emphasize that hier block generation is domain agnostic
- is_message_pad = pad.get_param('type').get_evaluated() == "message"
- if port.get_parent() == pad:
- if is_message_pad:
- key = pad.get_param('label').get_value()
- else:
- key = str(key_offset + int(port.get_key()))
- return key
- else:
- # assuming we have either only sources or sinks
- if not is_message_pad:
- key_offset += len(pad.get_ports())
- return -1
-
- def get_imports(self):
- """
- Get a set of all import statments in this flow graph namespace.
-
- Returns:
- a set of import statements
- """
- imports = sum([block.get_imports() for block in self.get_enabled_blocks()], [])
- imports = sorted(set(imports))
- return imports
-
- def get_variables(self):
- """
- Get a list of all variables in this flow graph namespace.
- Exclude paramterized variables.
-
- Returns:
- a sorted list of variable blocks in order of dependency (indep -> dep)
- """
- variables = filter(lambda b: _variable_matcher.match(b.get_key()), self.iter_enabled_blocks())
- return expr_utils.sort_objects(variables, methodcaller('get_id'), methodcaller('get_var_make'))
-
- def get_parameters(self):
- """
- Get a list of all paramterized variables in this flow graph namespace.
-
- Returns:
- a list of paramterized variables
- """
- parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.iter_enabled_blocks())
- return parameters
-
- def get_monitors(self):
- """
- Get a list of all ControlPort monitors
- """
- monitors = filter(lambda b: _monitors_searcher.search(b.get_key()),
- self.iter_enabled_blocks())
- return monitors
-
- def get_python_modules(self):
- """Iterate over custom code block ID and Source"""
- for block in self.iter_enabled_blocks():
- if block.get_key() == 'epy_module':
- yield block.get_id(), block.get_param('source_code').get_value()
-
- def get_bussink(self):
- bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks())
-
- for i in bussink:
- for j in i.get_params():
- if j.get_name() == 'On/Off' and j.get_value() == 'on':
- return True;
-
- return False
-
- def get_bussrc(self):
- bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks())
-
- for i in bussrc:
- for j in i.get_params():
- if j.get_name() == 'On/Off' and j.get_value() == 'on':
- return True;
-
- return False
-
- def get_bus_structure_sink(self):
- bussink = filter(lambda b: _bus_struct_sink_searcher.search(b.get_key()), self.get_enabled_blocks())
-
- return bussink
-
- def get_bus_structure_src(self):
- bussrc = filter(lambda b: _bus_struct_src_searcher.search(b.get_key()), self.get_enabled_blocks())
-
- return bussrc
-
- def rewrite(self):
- """
- Flag the namespace to be renewed.
- """
- def reconnect_bus_blocks():
- for block in self.get_blocks():
-
- if 'bus' in map(lambda a: a.get_type(), block.get_sources_gui()):
-
-
- for i in range(len(block.get_sources_gui())):
- if len(block.get_sources_gui()[i].get_connections()) > 0:
- source = block.get_sources_gui()[i]
- sink = []
-
- for j in range(len(source.get_connections())):
- sink.append(source.get_connections()[j].get_sink());
-
-
- for elt in source.get_connections():
- self.remove_element(elt);
- for j in sink:
- self.connect(source, j);
- self._renew_eval_ns = True
- _FlowGraph.rewrite(self);
- reconnect_bus_blocks();
-
- def evaluate(self, expr):
- """
- Evaluate the expression.
-
- Args:
- expr: the string expression
- @throw Exception bad expression
-
- Returns:
- the evaluated data
- """
- if self._renew_eval_ns:
- self._renew_eval_ns = False
- #reload namespace
- n = dict()
- #load imports
- for code in self.get_imports():
- try: exec code in n
- except: pass
-
- for id, code in self.get_python_modules():
- try:
- module = imp.new_module(id)
- exec code in module.__dict__
- n[id] = module
- except:
- pass
-
- #load parameters
- np = dict()
- for parameter in self.get_parameters():
- try:
- e = eval(parameter.get_param('value').to_code(), n, n)
- np[parameter.get_id()] = e
- except: pass
- n.update(np) #merge param namespace
- #load variables
- for variable in self.get_variables():
- try:
- e = eval(variable.get_var_value(), n, n)
- n[variable.get_id()] = e
- except: pass
- #make namespace public
- self.n = n
- self.n_hash = hash(str(n))
- #evaluate
- e = self._eval(expr, self.n, self.n_hash)
- return e
-
- def get_new_block(self, key):
- """Try to auto-generate the block from file if missing"""
- block = _FlowGraph.get_new_block(self, key)
- if not block:
- platform = self.get_parent()
- # we're before the initial fg rewrite(), so no evaluated values!
- # --> use raw value instead
- path_param = self._options_block.get_param('hier_block_src_path')
- file_path = platform.find_file_in_paths(
- filename=key + '.' + platform.get_key(),
- paths=path_param.get_value(),
- cwd=self.grc_file_path
- )
- if file_path: # grc file found. load and get block
- platform.load_and_generate_flow_graph(file_path)
- block = _FlowGraph.get_new_block(self, key) # can be None
- return block
diff --git a/grc/python/Param.py b/grc/python/Param.py
deleted file mode 100644
index e60f613f00..0000000000
--- a/grc/python/Param.py
+++ /dev/null
@@ -1,433 +0,0 @@
-"""
-Copyright 2008-2011 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 ast
-import re
-
-from gnuradio import gr
-
-from .. base.Param import Param as _Param
-from .. gui.Param import Param as _GUIParam
-
-import Constants
-from Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES
-
-from gnuradio import eng_notation
-
-_check_id_matcher = re.compile('^[a-z|A-Z]\w*$')
-_show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook|epy_module)$')
-
-
-#blacklist certain ids, its not complete, but should help
-import __builtin__
-ID_BLACKLIST = ['self', 'options', 'gr', 'blks2', 'wxgui', 'wx', 'math', 'forms', 'firdes'] + \
- filter(lambda x: not x.startswith('_'), dir(gr.top_block())) + dir(__builtin__)
-
-
-def num_to_str(num):
- """ Display logic for numbers """
- if isinstance(num, COMPLEX_TYPES):
- num = complex(num) #cast to python complex
- if num == 0: return '0' #value is zero
- elif num.imag == 0: return '%s'%eng_notation.num_to_str(num.real) #value is real
- elif num.real == 0: return '%sj'%eng_notation.num_to_str(num.imag) #value is imaginary
- elif num.imag < 0: return '%s-%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(abs(num.imag)))
- else: return '%s+%sj'%(eng_notation.num_to_str(num.real), eng_notation.num_to_str(num.imag))
- else: return str(num)
-
-
-class Param(_Param, _GUIParam):
-
- def __init__(self, **kwargs):
- _Param.__init__(self, **kwargs)
- _GUIParam.__init__(self)
- self._init = False
- self._hostage_cells = list()
-
- def get_types(self): return (
- 'raw', 'enum',
- 'complex', 'real', 'float', 'int',
- 'complex_vector', 'real_vector', 'float_vector', 'int_vector',
- 'hex', 'string', 'bool',
- 'file_open', 'file_save', '_multiline', '_multiline_python_external',
- 'id', 'stream_id',
- 'grid_pos', 'notebook', 'gui_hint',
- 'import',
- )
-
- def __repr__(self):
- """
- Get the repr (nice string format) for this param.
-
- Returns:
- the string representation
- """
- ##################################################
- # truncate helper method
- ##################################################
- def _truncate(string, style=0):
- max_len = max(27 - len(self.get_name()), 3)
- if len(string) > max_len:
- if style < 0: #front truncate
- string = '...' + string[3-max_len:]
- elif style == 0: #center truncate
- string = string[:max_len/2 -3] + '...' + string[-max_len/2:]
- elif style > 0: #rear truncate
- string = string[:max_len-3] + '...'
- return string
- ##################################################
- # simple conditions
- ##################################################
- if not self.is_valid(): return _truncate(self.get_value())
- if self.get_value() in self.get_option_keys(): return self.get_option(self.get_value()).get_name()
-
- ##################################################
- # split up formatting by type
- ##################################################
- truncate = 0 #default center truncate
- e = self.get_evaluated()
- t = self.get_type()
- if isinstance(e, bool): return str(e)
- elif isinstance(e, COMPLEX_TYPES): dt_str = num_to_str(e)
- elif isinstance(e, VECTOR_TYPES): #vector types
- if len(e) > 8:
- dt_str = self.get_value() #large vectors use code
- truncate = 1
- else: dt_str = ', '.join(map(num_to_str, e)) #small vectors use eval
- elif t in ('file_open', 'file_save'):
- dt_str = self.get_value()
- truncate = -1
- else: dt_str = str(e) #other types
- ##################################################
- # done
- ##################################################
- return _truncate(dt_str, truncate)
-
- def get_color(self):
- """
- Get the color that represents this param's type.
-
- Returns:
- a hex color code.
- """
- try:
- return {
- #number types
- 'complex': Constants.COMPLEX_COLOR_SPEC,
- 'real': Constants.FLOAT_COLOR_SPEC,
- 'float': Constants.FLOAT_COLOR_SPEC,
- 'int': Constants.INT_COLOR_SPEC,
- #vector types
- 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC,
- 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC,
- 'float_vector': Constants.FLOAT_VECTOR_COLOR_SPEC,
- 'int_vector': Constants.INT_VECTOR_COLOR_SPEC,
- #special
- 'bool': Constants.INT_COLOR_SPEC,
- 'hex': Constants.INT_COLOR_SPEC,
- 'string': Constants.BYTE_VECTOR_COLOR_SPEC,
- 'id': Constants.ID_COLOR_SPEC,
- 'stream_id': Constants.ID_COLOR_SPEC,
- 'grid_pos': Constants.INT_VECTOR_COLOR_SPEC,
- 'notebook': Constants.INT_VECTOR_COLOR_SPEC,
- 'raw': Constants.WILDCARD_COLOR_SPEC,
- }[self.get_type()]
- except: return _Param.get_color(self)
-
- def get_hide(self):
- """
- Get the hide value from the base class.
- Hide the ID parameter for most blocks. Exceptions below.
- If the parameter controls a port type, vlen, or nports, return part.
- If the parameter is an empty grid position, return part.
- These parameters are redundant to display in the flow graph view.
-
- Returns:
- hide the hide property string
- """
- hide = _Param.get_hide(self)
- if hide: return hide
- #hide ID in non variable blocks
- if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): return 'part'
- #hide port controllers for type and nports
- if self.get_key() in ' '.join(map(
- lambda p: ' '.join([p._type, p._nports]), self.get_parent().get_ports())
- ): return 'part'
- #hide port controllers for vlen, when == 1
- if self.get_key() in ' '.join(map(
- lambda p: p._vlen, self.get_parent().get_ports())
- ):
- try:
- if int(self.get_evaluated()) == 1: return 'part'
- except: pass
- #hide empty grid positions
- if self.get_key() in ('grid_pos', 'notebook') and not self.get_value(): return 'part'
- return hide
-
- def validate(self):
- """
- Validate the param.
- A test evaluation is performed
- """
- _Param.validate(self) #checks type
- self._evaluated = None
- try: self._evaluated = self.evaluate()
- except Exception, e: self.add_error_message(str(e))
-
- def get_evaluated(self): return self._evaluated
-
- def evaluate(self):
- """
- Evaluate the value.
-
- Returns:
- evaluated type
- """
- self._init = True
- self._lisitify_flag = False
- self._stringify_flag = False
- self._hostage_cells = list()
- t = self.get_type()
- v = self.get_value()
- #########################
- # Enum Type
- #########################
- if self.is_enum(): return v
- #########################
- # Numeric Types
- #########################
- elif t in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'):
- #raise exception if python cannot evaluate this value
- try: e = self.get_parent().get_parent().evaluate(v)
- except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e)
- #raise an exception if the data is invalid
- if t == 'raw': return e
- elif t == 'complex':
- if not isinstance(e, COMPLEX_TYPES):
- raise Exception, 'Expression "%s" is invalid for type complex.'%str(e)
- return e
- elif t == 'real' or t == 'float':
- if not isinstance(e, REAL_TYPES):
- raise Exception, 'Expression "%s" is invalid for type float.'%str(e)
- return e
- elif t == 'int':
- if not isinstance(e, INT_TYPES):
- raise Exception, 'Expression "%s" is invalid for type integer.'%str(e)
- return e
- elif t == 'hex': return hex(e)
- elif t == 'bool':
- if not isinstance(e, bool):
- raise Exception, 'Expression "%s" is invalid for type bool.'%str(e)
- return e
- else: raise TypeError, 'Type "%s" not handled'%t
- #########################
- # Numeric Vector Types
- #########################
- elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'):
- if not v: v = '()' #turn a blank string into an empty list, so it will eval
- #raise exception if python cannot evaluate this value
- try: e = self.get_parent().get_parent().evaluate(v)
- except Exception, e: raise Exception, 'Value "%s" cannot be evaluated:\n%s'%(v, e)
- #raise an exception if the data is invalid
- if t == 'complex_vector':
- if not isinstance(e, VECTOR_TYPES):
- self._lisitify_flag = True
- e = [e]
- if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]):
- raise Exception, 'Expression "%s" is invalid for type complex vector.'%str(e)
- return e
- elif t == 'real_vector' or t == 'float_vector':
- if not isinstance(e, VECTOR_TYPES):
- self._lisitify_flag = True
- e = [e]
- if not all([isinstance(ei, REAL_TYPES) for ei in e]):
- raise Exception, 'Expression "%s" is invalid for type float vector.'%str(e)
- return e
- elif t == 'int_vector':
- if not isinstance(e, VECTOR_TYPES):
- self._lisitify_flag = True
- e = [e]
- if not all([isinstance(ei, INT_TYPES) for ei in e]):
- raise Exception, 'Expression "%s" is invalid for type integer vector.'%str(e)
- return e
- #########################
- # String Types
- #########################
- elif t in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'):
- #do not check if file/directory exists, that is a runtime issue
- try:
- e = self.get_parent().get_parent().evaluate(v)
- if not isinstance(e, str):
- raise Exception()
- except:
- self._stringify_flag = True
- e = str(v)
- if t == '_multiline_python_external':
- ast.parse(e) # raises SyntaxError
- return e
- #########################
- # Unique ID Type
- #########################
- elif t == 'id':
- #can python use this as a variable?
- if not _check_id_matcher.match(v):
- raise Exception, 'ID "%s" must begin with a letter and may contain letters, numbers, and underscores.'%v
- ids = [param.get_value() for param in self.get_all_params(t)]
- if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled
- raise Exception, 'ID "%s" is not unique.'%v
- if v in ID_BLACKLIST:
- raise Exception, 'ID "%s" is blacklisted.'%v
- return v
- #########################
- # Stream ID Type
- #########################
- elif t == 'stream_id':
- #get a list of all stream ids used in the virtual sinks
- ids = [param.get_value() for param in filter(
- lambda p: p.get_parent().is_virtual_sink(),
- self.get_all_params(t),
- )]
- #check that the virtual sink's stream id is unique
- if self.get_parent().is_virtual_sink():
- if ids.count(v) > 1: #id should only appear once, or zero times if block is disabled
- raise Exception, 'Stream ID "%s" is not unique.'%v
- #check that the virtual source's steam id is found
- if self.get_parent().is_virtual_source():
- if v not in ids:
- raise Exception, 'Stream ID "%s" is not found.'%v
- return v
- #########################
- # GUI Position/Hint
- #########################
- elif t == 'gui_hint':
- if ':' in v: tab, pos = v.split(':')
- elif '@' in v: tab, pos = v, ''
- else: tab, pos = '', v
-
- if '@' in tab: tab, index = tab.split('@')
- else: index = '?'
-
- widget_str = ({
- (True, True): 'self.%(tab)s_grid_layout_%(index)s.addWidget(%(widget)s, %(pos)s)',
- (True, False): 'self.%(tab)s_layout_%(index)s.addWidget(%(widget)s)',
- (False, True): 'self.top_grid_layout.addWidget(%(widget)s, %(pos)s)',
- (False, False): 'self.top_layout.addWidget(%(widget)s)',
- }[bool(tab), bool(pos)])%{'tab': tab, 'index': index, 'widget': '%s', 'pos': pos}
-
- # FIXME: Move replace(...) into the make template of the qtgui blocks and return a string here
- class GuiHint(object):
- def __init__(self, ws):
- self._ws = ws
-
- def __call__(self, w):
- return (self._ws.replace('addWidget', 'addLayout') if 'layout' in w else self._ws) % w
-
- def __str__(self):
- return self._ws
- return GuiHint(widget_str)
- #########################
- # Grid Position Type
- #########################
- elif t == 'grid_pos':
- if not v: return '' #allow for empty grid pos
- e = self.get_parent().get_parent().evaluate(v)
- if not isinstance(e, (list, tuple)) or len(e) != 4 or not all([isinstance(ei, int) for ei in e]):
- raise Exception, 'A grid position must be a list of 4 integers.'
- row, col, row_span, col_span = e
- #check row, col
- if row < 0 or col < 0:
- raise Exception, 'Row and column must be non-negative.'
- #check row span, col span
- if row_span <= 0 or col_span <= 0:
- raise Exception, 'Row and column span must be greater than zero.'
- #get hostage cell parent
- try: my_parent = self.get_parent().get_param('notebook').evaluate()
- except: my_parent = ''
- #calculate hostage cells
- for r in range(row_span):
- for c in range(col_span):
- self._hostage_cells.append((my_parent, (row+r, col+c)))
- #avoid collisions
- params = filter(lambda p: p is not self, self.get_all_params('grid_pos'))
- for param in params:
- for parent, cell in param._hostage_cells:
- if (parent, cell) in self._hostage_cells:
- raise Exception, 'Another graphical element is using parent "%s", cell "%s".'%(str(parent), str(cell))
- return e
- #########################
- # Notebook Page Type
- #########################
- elif t == 'notebook':
- if not v: return '' #allow for empty notebook
- #get a list of all notebooks
- notebook_blocks = filter(lambda b: b.get_key() == 'notebook', self.get_parent().get_parent().get_enabled_blocks())
- #check for notebook param syntax
- try: notebook_id, page_index = map(str.strip, v.split(','))
- except: raise Exception, 'Bad notebook page format.'
- #check that the notebook id is valid
- try: notebook_block = filter(lambda b: b.get_id() == notebook_id, notebook_blocks)[0]
- except: raise Exception, 'Notebook id "%s" is not an existing notebook id.'%notebook_id
- #check that page index exists
- if int(page_index) not in range(len(notebook_block.get_param('labels').evaluate())):
- raise Exception, 'Page index "%s" is not a valid index number.'%page_index
- return notebook_id, page_index
- #########################
- # Import Type
- #########################
- elif t == 'import':
- n = dict() #new namespace
- try: exec v in n
- except ImportError: raise Exception, 'Import "%s" failed.'%v
- except Exception: raise Exception, 'Bad import syntax: "%s".'%v
- return filter(lambda k: str(k) != '__builtins__', n.keys())
- #########################
- else: raise TypeError, 'Type "%s" not handled'%t
-
- def to_code(self):
- """
- Convert the value to code.
- For string and list types, check the init flag, call evaluate().
- This ensures that evaluate() was called to set the xxxify_flags.
-
- Returns:
- a string representing the code
- """
- v = self.get_value()
- t = self.get_type()
- if t in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'): # string types
- if not self._init: self.evaluate()
- if self._stringify_flag: return '"%s"'%v.replace('"', '\"')
- else: return v
- elif t in ('complex_vector', 'real_vector', 'float_vector', 'int_vector'): #vector types
- if not self._init: self.evaluate()
- if self._lisitify_flag: return '(%s, )'%v
- else: return '(%s)'%v
- else: return v
-
- def get_all_params(self, type):
- """
- Get all the params from the flowgraph that have the given type.
-
- Args:
- type: the specified type
-
- Returns:
- a list of params
- """
- return sum([filter(lambda p: p.get_type() == type, block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], [])
diff --git a/grc/python/Platform.py b/grc/python/Platform.py
deleted file mode 100644
index 2a0bbf9a9e..0000000000
--- a/grc/python/Platform.py
+++ /dev/null
@@ -1,174 +0,0 @@
-"""
-Copyright 2008-2016 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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 os
-import sys
-
-from gnuradio import gr
-
-from .. base.Platform import Platform as _Platform
-from .. gui.Platform import Platform as _GUIPlatform
-from .. gui import Messages
-
-from . import extract_docs
-from .FlowGraph import FlowGraph as _FlowGraph
-from .Connection import Connection as _Connection
-from .Block import Block as _Block
-from .Port import Port as _Port
-from .Param import Param as _Param
-from .Generator import Generator
-from .Constants import (
- HIER_BLOCKS_LIB_DIR, BLOCK_DTD, DEFAULT_FLOW_GRAPH, BLOCKS_DIRS,
- PREFS_FILE, PREFS_FILE_OLD, CORE_TYPES
-)
-
-COLORS = [(name, color) for name, key, sizeof, color in CORE_TYPES]
-
-
-class Platform(_Platform, _GUIPlatform):
- def __init__(self):
- """
- Make a platform for gnuradio.
- """
- # ensure hier and conf directories
- if not os.path.exists(HIER_BLOCKS_LIB_DIR):
- os.mkdir(HIER_BLOCKS_LIB_DIR)
- if not os.path.exists(os.path.dirname(PREFS_FILE)):
- os.mkdir(os.path.dirname(PREFS_FILE))
-
- self.block_docstrings = block_docstrings = dict()
- self.block_docstrings_loaded_callback = lambda: None
-
- def setter(key, docs):
- block_docstrings[key] = '\n\n'.join(
- '--- {0} ---\n{1}\n'.format(b, d.replace('\n\n', '\n'))
- for b, d in docs.iteritems() if d is not None
- )
-
- self._docstring_extractor = extract_docs.SubprocessLoader(
- callback_query_result=setter,
- callback_finished=lambda: self.block_docstrings_loaded_callback()
- )
-
- # init
- _Platform.__init__(
- self,
- name='GNU Radio Companion',
- version=(gr.version(), gr.major_version(), gr.api_version(), gr.minor_version()),
- key='grc',
- license=__doc__.strip(),
- website='http://gnuradio.org/',
- block_paths=BLOCKS_DIRS,
- block_dtd=BLOCK_DTD,
- default_flow_graph=DEFAULT_FLOW_GRAPH,
- generator=Generator,
- colors=COLORS,
- )
- self._move_old_pref_file()
- _GUIPlatform.__init__(
- self,
- prefs_file=PREFS_FILE
- )
- self._auto_hier_block_generate_chain = set()
-
- @staticmethod
- def _move_old_pref_file():
- if PREFS_FILE == PREFS_FILE_OLD:
- return # prefs file overridden with env var
- if os.path.exists(PREFS_FILE_OLD) and not os.path.exists(PREFS_FILE):
- try:
- import shutil
- shutil.move(PREFS_FILE_OLD, PREFS_FILE)
- except Exception as e:
- print >> sys.stderr, e
-
- def load_blocks(self):
- self._docstring_extractor.start()
- _Platform.load_blocks(self)
- self._docstring_extractor.finish()
- # self._docstring_extractor.wait()
-
- def load_block_xml(self, xml_file):
- block = _Platform.load_block_xml(self, xml_file)
- self._docstring_extractor.query(
- block.get_key(),
- block.get_imports(raw=True),
- block.get_make(raw=True)
- )
- return block
-
- @staticmethod
- def find_file_in_paths(filename, paths, cwd):
- """Checks the provided paths relative to cwd for a certain filename"""
- if not os.path.isdir(cwd):
- cwd = os.path.dirname(cwd)
- if isinstance(paths, str):
- paths = (p for p in paths.split(':') if p)
-
- for path in paths:
- path = os.path.expanduser(path)
- if not os.path.isabs(path):
- path = os.path.normpath(os.path.join(cwd, path))
- file_path = os.path.join(path, filename)
- if os.path.exists(os.path.normpath(file_path)):
- return file_path
-
- def load_and_generate_flow_graph(self, file_path):
- """Loads a flowgraph from file and generates it"""
- Messages.set_indent(len(self._auto_hier_block_generate_chain))
- Messages.send('>>> Loading: %r\n' % file_path)
- if file_path in self._auto_hier_block_generate_chain:
- Messages.send(' >>> Warning: cyclic hier_block dependency\n')
- return False
- self._auto_hier_block_generate_chain.add(file_path)
- try:
- flow_graph = self.get_new_flow_graph()
- flow_graph.grc_file_path = file_path
- # other, nested higiter_blocks might be auto-loaded here
- flow_graph.import_data(self.parse_flow_graph(file_path))
- flow_graph.rewrite()
- flow_graph.validate()
- if not flow_graph.is_valid():
- raise Exception('Flowgraph invalid')
- except Exception as e:
- Messages.send('>>> Load Error: %r: %s\n' % (file_path, str(e)))
- return False
- finally:
- self._auto_hier_block_generate_chain.discard(file_path)
- Messages.set_indent(len(self._auto_hier_block_generate_chain))
-
- try:
- Messages.send('>>> Generating: %r\n' % file_path)
- generator = self.get_generator()(flow_graph, file_path)
- generator.write()
- except Exception as e:
- Messages.send('>>> Generate Error: %r: %s\n' % (file_path, str(e)))
- return False
-
- self.load_block_xml(generator.get_file_path_xml())
- return True
-
- ##############################################
- # Constructors
- ##############################################
- FlowGraph = _FlowGraph
- Connection = _Connection
- Block = _Block
- Port = _Port
- Param = _Param
diff --git a/grc/python/Port.py b/grc/python/Port.py
deleted file mode 100644
index 249d7aed71..0000000000
--- a/grc/python/Port.py
+++ /dev/null
@@ -1,268 +0,0 @@
-"""
-Copyright 2008-2012 Free Software Foundation, Inc.
-This file is part of GNU Radio
-
-GNU Radio Companion 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 2
-of the License, or (at your option) any later version.
-
-GNU Radio Companion 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
-"""
-
-from .. base.Port import Port as _Port
-from .. base.Constants import DEFAULT_DOMAIN, GR_MESSAGE_DOMAIN
-from .. gui.Port import Port as _GUIPort
-import Constants
-
-
-def _get_source_from_virtual_sink_port(vsp):
- """
- Resolve the source port that is connected to the given virtual sink port.
- Use the get source from virtual source to recursively resolve subsequent ports.
- """
- try: return _get_source_from_virtual_source_port(
- vsp.get_enabled_connections()[0].get_source())
- except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp
-
-def _get_source_from_virtual_source_port(vsp, traversed=[]):
- """
- Recursively resolve source ports over the virtual connections.
- Keep track of traversed sources to avoid recursive loops.
- """
- if not vsp.get_parent().is_virtual_source(): return vsp
- if vsp in traversed: raise Exception, 'Loop found when resolving virtual source %s'%vsp
- try: return _get_source_from_virtual_source_port(
- _get_source_from_virtual_sink_port(
- filter(#get all virtual sinks with a matching stream id
- lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
- filter(#get all enabled blocks that are also virtual sinks
- lambda b: b.is_virtual_sink(),
- vsp.get_parent().get_parent().get_enabled_blocks(),
- ),
- )[0].get_sinks()[0]
- ), traversed + [vsp],
- )
- except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
-
-def _get_sink_from_virtual_source_port(vsp):
- """
- Resolve the sink port that is connected to the given virtual source port.
- Use the get sink from virtual sink to recursively resolve subsequent ports.
- """
- try: return _get_sink_from_virtual_sink_port(
- vsp.get_enabled_connections()[0].get_sink()) # Could have many connections, but use first
- except: raise Exception, 'Could not resolve source for virtual source port %s'%vsp
-
-def _get_sink_from_virtual_sink_port(vsp, traversed=[]):
- """
- Recursively resolve sink ports over the virtual connections.
- Keep track of traversed sinks to avoid recursive loops.
- """
- if not vsp.get_parent().is_virtual_sink(): return vsp
- if vsp in traversed: raise Exception, 'Loop found when resolving virtual sink %s'%vsp
- try: return _get_sink_from_virtual_sink_port(
- _get_sink_from_virtual_source_port(
- filter(#get all virtual source with a matching stream id
- lambda vs: vs.get_param('stream_id').get_value() == vsp.get_parent().get_param('stream_id').get_value(),
- filter(#get all enabled blocks that are also virtual sinks
- lambda b: b.is_virtual_source(),
- vsp.get_parent().get_parent().get_enabled_blocks(),
- ),
- )[0].get_sources()[0]
- ), traversed + [vsp],
- )
- except: raise Exception, 'Could not resolve source for virtual sink port %s'%vsp
-
-class Port(_Port, _GUIPort):
-
- def __init__(self, block, n, dir):
- """
- Make a new port from nested data.
-
- Args:
- block: the parent element
- n: the nested odict
- dir: the direction
- """
- self._n = n
- if n['type'] == 'message':
- n['domain'] = GR_MESSAGE_DOMAIN
- if 'domain' not in n:
- n['domain'] = DEFAULT_DOMAIN
- elif n['domain'] == GR_MESSAGE_DOMAIN:
- n['key'] = n['name']
- n['type'] = 'message' # for port color
- if n['type'] == 'msg':
- n['key'] = 'msg'
- if not n.find('key'):
- n['key'] = str(next(block.port_counters[dir == 'source']))
- # build the port
- _Port.__init__(
- self,
- block=block,
- n=n,
- dir=dir,
- )
- _GUIPort.__init__(self)
- self._nports = n.find('nports') or ''
- self._vlen = n.find('vlen') or ''
- self._optional = bool(n.find('optional'))
- self._clones = [] # references to cloned ports (for nports > 1)
-
- def get_types(self): return Constants.TYPE_TO_SIZEOF.keys()
-
- def is_type_empty(self): return not self._n['type']
-
- def validate(self):
- _Port.validate(self)
- if not self.get_enabled_connections() and not self.get_optional():
- self.add_error_message('Port is not connected.')
- #message port logic
- if self.get_type() == 'msg':
- if self.get_nports():
- self.add_error_message('A port of type "msg" cannot have "nports" set.')
- if self.get_vlen() != 1:
- self.add_error_message('A port of type "msg" must have a "vlen" of 1.')
-
- def rewrite(self):
- """
- Handle the port cloning for virtual blocks.
- """
- if self.is_type_empty():
- try: #clone type and vlen
- source = self.resolve_empty_type()
- self._type = str(source.get_type())
- self._vlen = str(source.get_vlen())
- except: #reset type and vlen
- self._type = ''
- self._vlen = ''
- _Port.rewrite(self)
-
- def resolve_virtual_source(self):
- if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self)
- if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self)
-
- def resolve_empty_type(self):
- if self.is_sink():
- try:
- src = _get_source_from_virtual_sink_port(self)
- if not src.is_type_empty(): return src
- except: pass
- sink = _get_sink_from_virtual_sink_port(self)
- if not sink.is_type_empty(): return sink
- if self.is_source():
- try:
- src = _get_source_from_virtual_source_port(self)
- if not src.is_type_empty(): return src
- except: pass
- sink = _get_sink_from_virtual_source_port(self)
- if not sink.is_type_empty(): return sink
-
- def get_vlen(self):
- """
- Get the vector length.
- If the evaluation of vlen cannot be cast to an integer, return 1.
-
- Returns:
- the vector length or 1
- """
- vlen = self.get_parent().resolve_dependencies(self._vlen)
- try: return int(self.get_parent().get_parent().evaluate(vlen))
- except: return 1
-
- def get_nports(self):
- """
- Get the number of ports.
- If already blank, return a blank
- If the evaluation of nports cannot be cast to a positive integer, return 1.
-
- Returns:
- the number of ports or 1
- """
- if self._nports == '': return ''
-
- nports = self.get_parent().resolve_dependencies(self._nports)
- try:
- return max(1, int(self.get_parent().get_parent().evaluate(nports)))
- except:
- return 1
-
- def get_optional(self): return bool(self._optional)
-
- def get_color(self):
- """
- Get the color that represents this port's type.
- Codes differ for ports where the vec length is 1 or greater than 1.
-
- Returns:
- a hex color code.
- """
- try:
- color = Constants.TYPE_TO_COLOR[self.get_type()]
- vlen = self.get_vlen()
- if vlen == 1: return color
- color_val = int(color[1:], 16)
- r = (color_val >> 16) & 0xff
- g = (color_val >> 8) & 0xff
- b = (color_val >> 0) & 0xff
- dark = (0, 0, 30, 50, 70)[min(4, vlen)]
- r = max(r-dark, 0)
- g = max(g-dark, 0)
- b = max(b-dark, 0)
- return '#%.2x%.2x%.2x'%(r, g, b)
- except: return _Port.get_color(self)
-
- def get_clones(self):
- """
- Get the clones of this master port (nports > 1)
-
- Returns:
- a list of ports
- """
- return self._clones
-
- def add_clone(self):
- """
- Create a clone of this (master) port and store a reference in self._clones.
-
- The new port name (and key for message ports) will have index 1... appended.
- If this is the first clone, this (master) port will get a 0 appended to its name (and key)
-
- Returns:
- the cloned port
- """
- # add index to master port name if there are no clones yet
- if not self._clones:
- self._name = self._n['name'] + '0'
- if not self._key.isdigit(): # also update key for none stream ports
- self._key = self._name
-
- # Prepare a copy of the odict for the clone
- n = self._n.copy()
- if 'nports' in n: n.pop('nports') # remove nports from the key so the copy cannot be a duplicator
- n['name'] = self._n['name'] + str(len(self._clones) + 1)
- n['key'] = '99999' if self._key.isdigit() else n['name'] # dummy value 99999 will be fixed later
-
- port = self.__class__(self.get_parent(), n, self._dir) # clone
- self._clones.append(port)
- return port
-
- def remove_clone(self, port):
- """
- Remove a cloned port (from the list of clones only)
- Remove the index 0 of the master port name (and key9 if there are no more clones left
- """
- self._clones.remove(port)
- # remove index from master port name if there are no more clones
- if not self._clones:
- self._name = self._n['name']
- if not self._key.isdigit(): # also update key for none stream ports
- self._key = self._name
diff --git a/grc/scripts/CMakeLists.txt b/grc/scripts/CMakeLists.txt
index e905892308..6cc78c3cf3 100644
--- a/grc/scripts/CMakeLists.txt
+++ b/grc/scripts/CMakeLists.txt
@@ -23,3 +23,5 @@ GR_PYTHON_INSTALL(
DESTINATION ${GR_RUNTIME_DIR}
COMPONENT "grc"
)
+
+add_subdirectory(freedesktop)
diff --git a/grc/freedesktop/CMakeLists.txt b/grc/scripts/freedesktop/CMakeLists.txt
index 47e836f697..47e836f697 100644
--- a/grc/freedesktop/CMakeLists.txt
+++ b/grc/scripts/freedesktop/CMakeLists.txt
diff --git a/grc/freedesktop/README b/grc/scripts/freedesktop/README
index 0857ecc224..0857ecc224 100644
--- a/grc/freedesktop/README
+++ b/grc/scripts/freedesktop/README
diff --git a/grc/freedesktop/convert.sh b/grc/scripts/freedesktop/convert.sh
index e2cba264a6..e2cba264a6 100755
--- a/grc/freedesktop/convert.sh
+++ b/grc/scripts/freedesktop/convert.sh
diff --git a/grc/freedesktop/gnuradio-grc.desktop b/grc/scripts/freedesktop/gnuradio-grc.desktop
index 39beeca1b8..39beeca1b8 100644
--- a/grc/freedesktop/gnuradio-grc.desktop
+++ b/grc/scripts/freedesktop/gnuradio-grc.desktop
diff --git a/grc/freedesktop/gnuradio-grc.xml b/grc/scripts/freedesktop/gnuradio-grc.xml
index a5cb95d9fd..a5cb95d9fd 100644
--- a/grc/freedesktop/gnuradio-grc.xml
+++ b/grc/scripts/freedesktop/gnuradio-grc.xml
diff --git a/grc/freedesktop/gnuradio_logo_icon-square.svg b/grc/scripts/freedesktop/gnuradio_logo_icon-square.svg
index 3b54bf4001..3b54bf4001 100644
--- a/grc/freedesktop/gnuradio_logo_icon-square.svg
+++ b/grc/scripts/freedesktop/gnuradio_logo_icon-square.svg
diff --git a/grc/freedesktop/grc-icon-128.png b/grc/scripts/freedesktop/grc-icon-128.png
index 13efe806ba..13efe806ba 100644
--- a/grc/freedesktop/grc-icon-128.png
+++ b/grc/scripts/freedesktop/grc-icon-128.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-16.png b/grc/scripts/freedesktop/grc-icon-16.png
index bdd1823b3d..bdd1823b3d 100644
--- a/grc/freedesktop/grc-icon-16.png
+++ b/grc/scripts/freedesktop/grc-icon-16.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-24.png b/grc/scripts/freedesktop/grc-icon-24.png
index a124768125..a124768125 100644
--- a/grc/freedesktop/grc-icon-24.png
+++ b/grc/scripts/freedesktop/grc-icon-24.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-256.png b/grc/scripts/freedesktop/grc-icon-256.png
index 077688eac5..077688eac5 100644
--- a/grc/freedesktop/grc-icon-256.png
+++ b/grc/scripts/freedesktop/grc-icon-256.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-32.png b/grc/scripts/freedesktop/grc-icon-32.png
index a345aace3c..a345aace3c 100644
--- a/grc/freedesktop/grc-icon-32.png
+++ b/grc/scripts/freedesktop/grc-icon-32.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-48.png b/grc/scripts/freedesktop/grc-icon-48.png
index c522a5d0ec..c522a5d0ec 100644
--- a/grc/freedesktop/grc-icon-48.png
+++ b/grc/scripts/freedesktop/grc-icon-48.png
Binary files differ
diff --git a/grc/freedesktop/grc-icon-64.png b/grc/scripts/freedesktop/grc-icon-64.png
index df4f6dc07b..df4f6dc07b 100644
--- a/grc/freedesktop/grc-icon-64.png
+++ b/grc/scripts/freedesktop/grc-icon-64.png
Binary files differ
diff --git a/grc/freedesktop/grc_setup_freedesktop.in b/grc/scripts/freedesktop/grc_setup_freedesktop.in
index 87a388e2ec..87a388e2ec 100644
--- a/grc/freedesktop/grc_setup_freedesktop.in
+++ b/grc/scripts/freedesktop/grc_setup_freedesktop.in
diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion
index 203a8c773d..04a1cb44e7 100755
--- a/grc/scripts/gnuradio-companion
+++ b/grc/scripts/gnuradio-companion
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
-Copyright 2009-2015 Free Software Foundation, Inc.
+Copyright 2016 Free Software Foundation, Inc.
This file is part of GNU Radio
GNU Radio Companion is free software; you can redistribute it and/or
@@ -20,111 +20,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
import os
import sys
-import optparse
-import warnings
-
-GR_IMPORT_ERROR_MESSAGE = """\
-Cannot import gnuradio.
-
-Is the python path environment variable set correctly?
- All OS: PYTHONPATH
-
-Is the library path environment variable set correctly?
- Linux: LD_LIBRARY_PATH
- Windows: PATH
- MacOSX: DYLD_LIBRARY_PATH
-"""
-
-VERSION_AND_DISCLAIMER_TEMPLATE = """\
-GNU Radio Companion %s
-
-This program is part of GNU Radio
-GRC comes with ABSOLUTELY NO WARRANTY.
-This is free software, and you are welcome to redistribute it.
-"""
-
-
-def die(error, message):
- msg = "{0}\n\n({1})".format(message, error)
- try:
- import gtk
- d = gtk.MessageDialog(
- type=gtk.MESSAGE_ERROR,
- buttons=gtk.BUTTONS_CLOSE,
- message_format=msg,
- )
- d.set_title(type(error).__name__)
- d.run()
- exit(1)
- except ImportError:
- exit(type(error).__name__ + '\n\n' + msg)
-
-
-def check_gtk():
- try:
- warnings.filterwarnings("error")
- import pygtk
- pygtk.require('2.0')
- import gtk
- gtk.init_check()
- warnings.filterwarnings("always")
- except Exception as err:
- die(err, "Failed to initialize GTK. If you are running over ssh, "
- "did you enable X forwarding and start ssh with -X?")
-
-
-def check_gnuradio_import():
- try:
- from gnuradio import gr
- except ImportError as err:
- die(err, GR_IMPORT_ERROR_MESSAGE)
-
-
-def check_blocks_path():
- if 'GR_DONT_LOAD_PREFS' in os.environ and not os.environ.get('GRC_BLOCKS_PATH', ''):
- die(EnvironmentError("No block definitions available"),
- "Can't find block definitions. Use config.conf or GRC_BLOCKS_PATH.")
-
-
-def get_source_tree_root():
- source_tree_subpath = "/grc/scripts"
- script_path = os.path.dirname(os.path.abspath(__file__))
- if script_path.endswith(source_tree_subpath):
- return script_path[:-len(source_tree_subpath)]
-
-
-def main():
- check_gnuradio_import()
-
- from gnuradio import gr
- parser = optparse.OptionParser(
- usage='usage: %prog [options] [saved flow graphs]',
- version=VERSION_AND_DISCLAIMER_TEMPLATE % gr.version())
- options, args = parser.parse_args()
-
- check_gtk()
- check_blocks_path()
- source_tree_root = get_source_tree_root()
- if not source_tree_root:
- # run the installed version
- from gnuradio.grc.python.Platform import Platform
- from gnuradio.grc.gui.ActionHandler import ActionHandler
-
- else:
- print("Running from source tree")
- sys.path.insert(1, source_tree_root)
- from grc.python.Platform import Platform
- from grc.gui.ActionHandler import ActionHandler
-
- try:
- import gtk
- gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0))
- except:
- pass
-
- ActionHandler(args, Platform())
-
-
-if __name__ == '__main__':
- main()
+script_path = os.path.dirname(os.path.abspath(__file__))
+source_tree_subpath = "/grc/scripts"
+
+if not script_path.endswith(source_tree_subpath):
+ # run the installed version
+ from gnuradio.grc.main import main
+ from gnuradio.grc import checks
+else:
+ print("Running from source tree")
+ sys.path.insert(1, script_path[:-len(source_tree_subpath)])
+ from grc.main import main
+ from grc import checks
+
+checks.do_all()
+exit(main())
diff --git a/grc/todo.txt b/grc/todo.txt
deleted file mode 100644
index cedea72aa3..0000000000
--- a/grc/todo.txt
+++ /dev/null
@@ -1,69 +0,0 @@
-##################################################
-# Examples
-##################################################
-* Push-to-Talk example
-* Start/Stop the flow graph
-
-##################################################
-# Blocks
-##################################################
-* probe: also non-float outputs
-* log slider gui control
-* packet mod: whitening offset
-* wx min window size in options block
-* gr_adaptive_fir_ccf
-* size params for the graphical sinks
-* callbacks for set average on fft, waterfall, number sinks
-* add units to params: Sps, Hz, dB...
-* add bool type to command line option store_true or store_false
-* messages for packet blocks and probe blocks
-
-##################################################
-# Features
-##################################################
-* extract category from doxygen
- * fix up block tree to mirror current doxygen group
- * remove blocks in block tree covered by doxygen
-* param editor, expand entry boxes in focus
-* change param dialog to panel within main window
-* gui grid editor for configuring grid params/placing wxgui plots and controls
-* drag from one port to another to connect
-* per parameter docs
- * extract individual param docs from doxygen
- * doc tag in param for handwritten notes
-* separate generated code into top block and gui class
- * use gui.py in gr-wxgui and remove custom top_block_gui
-* configuration option for adding block paths
-* orientations for ports (top, right, bottom, left)
- * source defaults to right, sink defaults to left
-* separation of variables and gui controls
-* speedup w/ background layer and animation layer
-* multiple doxygen directories (doc_dir becomes doc_path)
-* use pango markup in tooltips for params
-* use get_var_make to determine if it is a variable, not regexp
-* concept of a project, or project flow graph
- * collection of blocks, hier and top
- * system-wide, default/work, and user created
-* use templates/macros to generate the repetative stuff in the xml
-
-##################################################
-# Problems
-##################################################
-* msg ports dont work with virtual connections
- * dont fix this until pmts are used?
-* hier block generation
- * auto generate hier library on changes
- * auto clean hier library when block removed
- * add hier blocks to tree without restart
-* dont generate py files in saved flowgraph dir
-* save/restore cwd
-* threads dont die on exit in probe and variable sink
-* align param titles in properties dialog
-* weird grid params misbehaving
-* gr hier blocks have more diverse IO capabilities than we allow for
-
-##################################################
-# Future
-##################################################
-* require pygtk 2.12 for treeview tooltips
- * remove try/except in BlockTreeWindow.py