summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt23
-rw-r--r--cmake/Modules/GnuradioConfig.cmake4
-rw-r--r--cmake/Modules/GrPython.cmake7
-rw-r--r--cmake/Modules/GrTest.cmake6
-rw-r--r--cmake/Toolchains/oe-sdk_cross.cmake13
-rw-r--r--docs/doxygen/CMakeLists.txt4
-rw-r--r--docs/doxygen/images/gnuradio-logo.pngbin5223 -> 0 bytes
-rw-r--r--docs/doxygen/images/gnuradio-logo.svg521
-rw-r--r--docs/doxygen/other/extra_pages.dox53
-rw-r--r--docs/doxygen/other/main_page.dox2
-rw-r--r--gnuradio-runtime/apps/gnuradio-config-info.cc23
-rw-r--r--gnuradio-runtime/include/gnuradio/constants.h15
-rw-r--r--gnuradio-runtime/lib/constants.cc.in18
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt2
-rw-r--r--gnuradio-runtime/python/pmt/CMakeLists.txt2
-rw-r--r--gr-analog/python/analog/CMakeLists.txt2
-rw-r--r--gr-atsc/python/atsc/CMakeLists.txt2
-rw-r--r--gr-audio/python/audio/CMakeLists.txt2
-rw-r--r--gr-blocks/grc/blocks_block_tree.xml1
-rw-r--r--gr-blocks/grc/blocks_tagged_stream_multiply_length.xml70
-rw-r--r--gr-blocks/grc/blocks_tags_strobe.xml9
-rw-r--r--gr-blocks/grc/blocks_throttle.xml8
-rw-r--r--gr-blocks/include/gnuradio/blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h60
-rw-r--r--gr-blocks/include/gnuradio/blocks/tags_strobe.h14
-rw-r--r--gr-blocks/include/gnuradio/blocks/throttle.h2
-rw-r--r--gr-blocks/lib/CMakeLists.txt1
-rw-r--r--gr-blocks/lib/add_ff_impl.cc10
-rw-r--r--gr-blocks/lib/conjugate_cc_impl.cc7
-rw-r--r--gr-blocks/lib/endian_swap_impl.cc59
-rw-r--r--gr-blocks/lib/multiply_cc_impl.cc11
-rw-r--r--gr-blocks/lib/multiply_conjugate_cc_impl.cc7
-rw-r--r--gr-blocks/lib/multiply_const_cc_impl.cc7
-rw-r--r--gr-blocks/lib/multiply_const_ff_impl.cc7
-rw-r--r--gr-blocks/lib/multiply_ff_impl.cc11
-rw-r--r--gr-blocks/lib/tagged_stream_multiply_length_impl.cc89
-rw-r--r--gr-blocks/lib/tagged_stream_multiply_length_impl.h62
-rw-r--r--gr-blocks/lib/tags_strobe_impl.cc20
-rw-r--r--gr-blocks/lib/tags_strobe_impl.h5
-rw-r--r--gr-blocks/lib/throttle_impl.cc26
-rw-r--r--gr-blocks/lib/throttle_impl.h3
-rw-r--r--gr-blocks/python/blocks/CMakeLists.txt2
-rw-r--r--gr-blocks/swig/blocks_swig5.i3
-rw-r--r--gr-channels/python/channels/CMakeLists.txt2
-rw-r--r--gr-comedi/python/comedi/CMakeLists.txt2
-rw-r--r--gr-digital/lib/constellation.cc8
-rw-r--r--gr-digital/python/digital/CMakeLists.txt2
-rw-r--r--gr-fcd/python/fcd/CMakeLists.txt2
-rw-r--r--gr-fec/python/fec/CMakeLists.txt2
-rw-r--r--gr-fft/include/gnuradio/fft/window.h42
-rw-r--r--gr-fft/lib/window.cc19
-rw-r--r--gr-fft/python/fft/CMakeLists.txt2
-rw-r--r--gr-filter/doc/filter.dox10
-rw-r--r--gr-filter/grc/filter_pfb_decimator.xml3
-rw-r--r--gr-filter/include/gnuradio/filter/CMakeLists.txt3
-rw-r--r--gr-filter/include/gnuradio/filter/adaptive_fir.h88
-rw-r--r--gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h87
-rw-r--r--gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h82
-rw-r--r--gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h2
-rw-r--r--gr-filter/lib/CMakeLists.txt3
-rw-r--r--gr-filter/lib/adaptive_fir.cc60
-rw-r--r--gr-filter/lib/adaptive_fir_ccc_impl.cc106
-rw-r--r--gr-filter/lib/adaptive_fir_ccc_impl.h62
-rw-r--r--gr-filter/lib/adaptive_fir_ccf_impl.cc106
-rw-r--r--gr-filter/lib/adaptive_fir_ccf_impl.h62
-rw-r--r--gr-filter/lib/firdes.cc25
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.cc7
-rw-r--r--gr-filter/lib/pfb_decimator_ccf_impl.h2
-rw-r--r--gr-filter/lib/qa_firdes.cc550
-rw-r--r--gr-filter/python/filter/CMakeLists.txt2
-rw-r--r--gr-filter/python/filter/pfb.py6
-rwxr-xr-xgr-filter/python/filter/qa_adaptive_fir_filter.py101
-rwxr-xr-xgr-filter/python/filter/qa_firdes.py95
-rwxr-xr-xgr-filter/python/filter/qa_freq_xlating_fir_filter.py4
-rw-r--r--gr-filter/swig/filter_swig.i6
-rw-r--r--gr-noaa/python/noaa/CMakeLists.txt2
-rw-r--r--gr-pager/python/pager/CMakeLists.txt2
-rw-r--r--gr-qtgui/grc/qtgui_freq_sink_x.xml4
-rw-r--r--gr-qtgui/grc/qtgui_waterfall_sink_x.xml4
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/form_menus.h241
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h5
-rw-r--r--gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h4
-rw-r--r--gr-qtgui/lib/freqdisplayform.cc21
-rw-r--r--gr-qtgui/lib/waterfalldisplayform.cc24
-rw-r--r--gr-qtgui/python/qtgui/CMakeLists.txt2
-rw-r--r--gr-trellis/python/trellis/CMakeLists.txt2
-rw-r--r--gr-uhd/python/uhd/CMakeLists.txt2
-rw-r--r--gr-utils/python/modtool/CMakeLists.txt1
-rw-r--r--gr-utils/python/modtool/__init__.py3
-rw-r--r--gr-utils/python/modtool/gr-newmod/CMakeLists.txt19
-rw-r--r--gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt2
-rw-r--r--gr-utils/python/modtool/modtool_add.py96
-rw-r--r--gr-utils/python/modtool/modtool_base.py40
-rw-r--r--gr-utils/python/modtool/modtool_disable.py20
-rw-r--r--gr-utils/python/modtool/modtool_help.py10
-rw-r--r--gr-utils/python/modtool/modtool_info.py38
-rw-r--r--gr-utils/python/modtool/modtool_makexml.py34
-rw-r--r--gr-utils/python/modtool/modtool_newmod.py28
-rw-r--r--gr-utils/python/modtool/modtool_rm.py23
-rw-r--r--gr-utils/python/modtool/scm.py221
-rw-r--r--gr-utils/python/modtool/util_functions.py9
-rwxr-xr-xgr-utils/python/utils/gr_modtool14
-rw-r--r--gr-video-sdl/python/video_sdl/CMakeLists.txt2
-rw-r--r--gr-vocoder/python/vocoder/CMakeLists.txt2
-rw-r--r--gr-wavelet/python/wavelet/CMakeLists.txt2
-rw-r--r--grc/base/FlowGraph.py25
-rw-r--r--grc/gui/ActionHandler.py14
-rw-r--r--grc/gui/Actions.py78
-rw-r--r--grc/gui/Bars.py5
-rw-r--r--grc/gui/BlockTreeWindow.py4
-rw-r--r--grc/gui/Connection.py5
-rw-r--r--grc/gui/MainWindow.py2
-rw-r--r--grc/gui/Preferences.py12
-rw-r--r--grc/python/Block.py69
-rw-r--r--grc/python/Port.py63
-rw-r--r--grc/python/flow_graph.tmpl2
-rw-r--r--volk/apps/CMakeLists.txt12
-rw-r--r--volk/apps/volk-config-info.cc96
-rw-r--r--volk/apps/volk_profile.cc202
-rw-r--r--volk/cmake/GrBoost.cmake1
-rw-r--r--volk/gen/archs.xml9
-rw-r--r--volk/gen/machines.xml2
-rw-r--r--volk/include/volk/constants.h39
-rw-r--r--volk/lib/CMakeLists.txt39
-rw-r--r--volk/lib/constants.c.in63
-rw-r--r--volk/lib/qa_utils.cc11
-rw-r--r--volk/lib/qa_utils.h6
-rw-r--r--volk/tmpl/volk.tmpl.c37
-rw-r--r--volk/tmpl/volk.tmpl.h6
129 files changed, 2538 insertions, 1888 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac267ecfb6..785d78b047 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,8 +41,8 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
# Set the version information here
set(VERSION_INFO_MAJOR_VERSION 3)
set(VERSION_INFO_API_COMPAT 7)
-set(VERSION_INFO_MINOR_VERSION 2)
-set(VERSION_INFO_MAINT_VERSION 1)
+set(VERSION_INFO_MINOR_VERSION 3)
+set(VERSION_INFO_MAINT_VERSION git)
include(GrVersion) #setup version info
# Append -O2 optimization flag for Debug builds
@@ -103,6 +103,25 @@ if(MSVC)
add_definitions(/bigobj) #allow for larger object files
endif(MSVC)
+# Record Compiler Info for record
+STRING(TOUPPER ${CMAKE_BUILD_TYPE} GRCBTU)
+set(COMPILER_INFO "")
+execute_process(COMMAND ${CMAKE_C_COMPILER} --version
+ OUTPUT_VARIABLE cmake_c_compiler_version)
+execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version
+ OUTPUT_VARIABLE cmake_cxx_compiler_version)
+set(COMPILER_INFO "${CMAKE_C_COMPILER}:::${CMAKE_C_FLAGS_${GRCBTU}} ${CMAKE_C_FLAGS}\n${CMAKE_CXX_COMPILER}:::${CMAKE_CXX_FLAGS_${GRCBTU}} ${CMAKE_CXX_FLAGS}\n" )
+
+# Convert to a C string to compile and display properly
+string(STRIP "${cmake_c_compiler_version}" cmake_c_compiler_version)
+string(STRIP "${cmake_cxx_compiler_version}" cmake_cxx_compiler_version)
+string(STRIP ${COMPILER_INFO} COMPILER_INFO)
+MESSAGE(STATUS "Compiler Version: ${cmake_c_compiler_version}")
+MESSAGE(STATUS "Compiler Flags: ${COMPILER_INFO}")
+string(REPLACE "\n" " \\n" cmake_c_compiler_version ${cmake_c_compiler_version})
+string(REPLACE "\n" " \\n" cmake_cxx_compiler_version ${cmake_cxx_compiler_version})
+string(REPLACE "\n" " \\n" COMPILER_INFO ${COMPILER_INFO})
+
########################################################################
# Install directories
########################################################################
diff --git a/cmake/Modules/GnuradioConfig.cmake b/cmake/Modules/GnuradioConfig.cmake
index e120abab94..55c70b374b 100644
--- a/cmake/Modules/GnuradioConfig.cmake
+++ b/cmake/Modules/GnuradioConfig.cmake
@@ -25,6 +25,10 @@ if(NOT GR_REQUIRED_COMPONENTS)
set(GR_REQUIRED_COMPONENTS RUNTIME ANALOG BLOCKS DIGITAL FFT FILTER PMT)
endif()
+# Allows us to use all .cmake files in this directory
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_LIST_DIR})
+
+# Easily access all libraries and includes of GNU Radio
set(GNURADIO_ALL_LIBRARIES "")
set(GNURADIO_ALL_INCLUDE_DIRS "")
diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake
index 26a5c9452b..d0d78863cc 100644
--- a/cmake/Modules/GrPython.cmake
+++ b/cmake/Modules/GrPython.cmake
@@ -48,8 +48,15 @@ else(PYTHON_EXECUTABLE)
endif(PYTHON_EXECUTABLE)
+if (CMAKE_CROSSCOMPILING)
+ set(QA_PYTHON_EXECUTABLE "/usr/bin/python")
+else (CMAKE_CROSSCOMPILING)
+ set(QA_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
+endif(CMAKE_CROSSCOMPILING)
+
#make the path to the executable appear in the cmake gui
set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
+set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests")
#make sure we can use -B with python (introduced in 2.6)
if(PYTHON_EXECUTABLE)
diff --git a/cmake/Modules/GrTest.cmake b/cmake/Modules/GrTest.cmake
index bb045dcbb3..7b642046e6 100644
--- a/cmake/Modules/GrTest.cmake
+++ b/cmake/Modules/GrTest.cmake
@@ -91,7 +91,11 @@ function(GR_ADD_TEST test_name)
list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
#generate a bat file that sets the environment and runs the test
- find_program(SHELL sh)
+ if (CMAKE_CROSSCOMPILING)
+ set(SHELL "/bin/sh")
+ else(CMAKE_CROSSCOMPILING)
+ find_program(SHELL sh)
+ endif(CMAKE_CROSSCOMPILING)
set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
file(WRITE ${sh_file} "#!${SHELL}\n")
#each line sets an environment variable
diff --git a/cmake/Toolchains/oe-sdk_cross.cmake b/cmake/Toolchains/oe-sdk_cross.cmake
new file mode 100644
index 0000000000..ea77815c96
--- /dev/null
+++ b/cmake/Toolchains/oe-sdk_cross.cmake
@@ -0,0 +1,13 @@
+set( CMAKE_SYSTEM_NAME Linux )
+#set( CMAKE_C_COMPILER $ENV{CC} )
+#set( CMAKE_CXX_COMPILER $ENV{CXX} )
+set( CMAKE_CXX_FLAGS $ENV{CXXFLAGS} CACHE STRING "" FORCE )
+set( CMAKE_C_FLAGS $ENV{CFLAGS} CACHE STRING "" FORCE ) #same flags for C sources
+set( CMAKE_LDFLAGS_FLAGS ${CMAKE_CXX_FLAGS} CACHE STRING "" FORCE ) #same flags for C sources
+set( CMAKE_LIBRARY_PATH ${OECORE_TARGET_SYSROOT}/usr/lib )
+set( CMAKE_FIND_ROOT_PATH $ENV{OECORE_NATIVE_SYSROOT} $ENV{OECORE_TARGET_SYSROOT} )
+set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+set ( ORC_INCLUDE_DIRS $ENV{OECORE_TARGET_SYSROOT}/usr/include/orc-0.4 )
+set ( ORC_LIBRARY_DIRS $ENV{OECORE_TARGET_SYSROOT}/usr/lib )
diff --git a/docs/doxygen/CMakeLists.txt b/docs/doxygen/CMakeLists.txt
index 8498511f9d..a837bd8e11 100644
--- a/docs/doxygen/CMakeLists.txt
+++ b/docs/doxygen/CMakeLists.txt
@@ -53,10 +53,6 @@ if(ENABLE_GR_DIGITAL)
list(APPEND GENERATED_DEPS digital_generated_includes)
endif(ENABLE_GR_DIGITAL)
-if(ENABLE_GR_FEC)
- list(APPEND GENERATED_DEPS fec_generated_includes)
-endif(ENABLE_GR_FEC)
-
if(ENABLE_GR_FILTER)
list(APPEND GENERATED_DEPS filter_generated_includes)
endif(ENABLE_GR_FILTER)
diff --git a/docs/doxygen/images/gnuradio-logo.png b/docs/doxygen/images/gnuradio-logo.png
deleted file mode 100644
index ec4db23fc8..0000000000
--- a/docs/doxygen/images/gnuradio-logo.png
+++ /dev/null
Binary files differ
diff --git a/docs/doxygen/images/gnuradio-logo.svg b/docs/doxygen/images/gnuradio-logo.svg
new file mode 100644
index 0000000000..7143bc2a38
--- /dev/null
+++ b/docs/doxygen/images/gnuradio-logo.svg
@@ -0,0 +1,521 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="650"
+ height="164"
+ id="svg3716"
+ version="1.1"
+ inkscape:version="0.48.3.1 r9886"
+ sodipodi:docname="gnuradio-logo3.svg">
+ <defs
+ id="defs3718" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.7"
+ inkscape:cx="333.61853"
+ inkscape:cy="-208.88012"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="843"
+ inkscape:window-height="720"
+ inkscape:window-x="510"
+ inkscape:window-y="445"
+ inkscape:window-maximized="0"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata3721">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0.71428519,1.0663847)">
+ <image
+ y="-1.0663847"
+ x="-0.71428519"
+ id="image3732"
+ xlink:href="data:image/png;base64,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
+7/L/7tLt1enPwIwAAAAASUVORK5CYII=
+"
+ height="164"
+ width="650" />
+ </g>
+</svg>
diff --git a/docs/doxygen/other/extra_pages.dox b/docs/doxygen/other/extra_pages.dox
index 617e00d553..88aee72ffe 100644
--- a/docs/doxygen/other/extra_pages.dox
+++ b/docs/doxygen/other/extra_pages.dox
@@ -119,7 +119,7 @@ built or installed.
The -DENABLE_DEFAULT=False can be used to disable all
components. Individual components can then be selectively turned back
-on. For example, just buidling the Volk library can be
+on. For example, just buidling the VOLK library can be
done with this:
\code
@@ -160,27 +160,27 @@ cmake -DCMAKE_CXX_FLAGS:STRING="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -g
-/*! \page volk_guide Instructions for using Volk in GNU Radio
+/*! \page volk_guide Instructions for using VOLK in GNU Radio
\section volk_intro Introduction
-Volk is the Vector-Optimized Library of Kernels. It is a library that
+VOLK is the Vector-Optimized Library of Kernels. It is a library that
contains kernels of hand-written SIMD code for different mathematical
operations. Since each SIMD architecture can be greatly different and
no compiler has yet come along to handle vectorization properly or
-highly efficiently, Volk approaches the problem differently. For each
+highly efficiently, VOLK approaches the problem differently. For each
architecture or platform that a developer wishes to vectorize for, a
-new proto-kernel is added to Volk. At runtime, Volk will select the
-correct proto-kernel. In this way, the users of Volk call a kernel for
+new proto-kernel is added to VOLK. At runtime, VOLK will select the
+correct proto-kernel. In this way, the users of VOLK call a kernel for
performing the operation that is platform/architecture agnostic. This
allows us to write portable SIMD code.
-Volk kernels are always defined with a 'generic' proto-kernel, which
+VOLK kernels are always defined with a 'generic' proto-kernel, which
is written in plain C. With the generic kernel, the kernel becomes
portable to any platform. Kernels are then extended by adding
proto-kernels for new platforms in which they are desired.
-A good example of a Volk kernel with multiple proto-kernels defined is
+A good example of a VOLK kernel with multiple proto-kernels defined is
the volk_32f_s32f_multiply_32f_a. This kernel implements a scalar
multiplication of a vector of floating point numbers (each item in the
vector is multiplied by the same value). This kernel has the following
@@ -193,10 +193,10 @@ proto-kernels that are defined for 'generic,' 'avx,' 'sse,' and 'orc.'
void volk_32f_s32f_multiply_32f_a_orc
\endcode
-These proto-kernels means that on platforms with AVX support, Volk can
+These proto-kernels means that on platforms with AVX support, VOLK can
select this option or the SSE option, depending on which is faster. On
other platforms, the ORC SIMD compiler might provide a solution. If
-all else fails, Volk can fall back on the generic proto-kernel, which
+all else fails, VOLK can fall back on the generic proto-kernel, which
will always work.
Just a note on ORC. ORC is a SIMD compiler library that uses a generic
@@ -210,13 +210,13 @@ step to performance improvements until a specific hand-tuned
proto-kernel can be made for a given platform.
See <a
-href="http://gnuradio.org/redmine/projects/gnuradio/wiki/Volk">Volk on
-gnuradio.org</a> for details on the Volk naming scheme.
+href="http://gnuradio.org/redmine/projects/gnuradio/wiki/Volk">VOLK on
+gnuradio.org</a> for details on the VOLK naming scheme.
\section volk_alignment Setting and Using Memory Alignment Information
-For Volk to work as best as possible, we want to use memory-aligned
+For VOLK to work as best as possible, we want to use memory-aligned
SIMD calls, which means we have to have some way of knowing and
controlling the alignment of the buffers passed to gr_block's work
function. We set the alignment requirement for SIMD aligned memory
@@ -228,7 +228,7 @@ calls with:
set_alignment(std::max(1,alignment_multiple));
\endcode
-The Volk function 'volk_get_alignment' provides the alignment of the
+The VOLK function 'volk_get_alignment' provides the alignment of the
the machine architecture. We then base the alignment on the number of
output items required to maintain the alignment, so we divide the
number of alignment bytes by the number of bytes in an output items
@@ -249,13 +249,16 @@ do. The next section discusses the use of the aligned/unaligned
information in a gr_block's work function.
-\section volk_work Using Alignment Properties in Work()
+\section volk_work Calling VOLK kernels in Work()
The buffers passed to work/general_work in a gr_block are not
guaranteed to be aligned, but they will mostly be aligned whenever
-possible. When not aligned, the 'is_unaligned()' flag will be set. So
-a block can know if its buffers are aligned and make the right
-decisions. This looks like:
+possible. When not aligned, the 'is_unaligned()' flag will be set so
+the scheduler knows to try to realign the buffers. We actually make
+calls to the VOLK dispatcher, which is mainly designed to check the
+buffer alignments and call the correct version of the kernel for
+us. From the user-level view of VOLK, calling the dispatcher allows us
+to ignore the concept of aligned versus unaligned. This looks like:
\code
int
@@ -266,15 +269,9 @@ gr_some_block::work (int noutput_items,
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
- if(is_unaligned()) {
- // do something with unaligned data. This can either be a manual
- // handling of the items or a call to an unaligned Volk function.
- volk_32f_something_32f_u(out, in, noutput_items);
- }
- else {
- // Buffers are aligned; can call the aligned Volk function.
- volk_32f_something_32f_a(out, in, noutput_items);
- }
+ // Call the dispatcher to check alignment and call the _a or _u
+ // version of the kernel.
+ volk_32f_something_32f(out, in, noutput_items);
return noutput_items;
}
@@ -282,7 +279,7 @@ gr_some_block::work (int noutput_items,
-\section volk_tuning Tuning Volk Performance
+\section volk_tuning Tuning VOLK Performance
VOLK comes with a profiler that will build a config file for the best
SIMD architecture for your processor. Run volk_profile that is
diff --git a/docs/doxygen/other/main_page.dox b/docs/doxygen/other/main_page.dox
index fdbf1c76b4..e2956384f6 100644
--- a/docs/doxygen/other/main_page.dox
+++ b/docs/doxygen/other/main_page.dox
@@ -1,6 +1,6 @@
/*! \mainpage
-\image html gnuradio-logo.png
+\image html gnuradio-logo.svg
Welcome to GNU Radio!
diff --git a/gnuradio-runtime/apps/gnuradio-config-info.cc b/gnuradio-runtime/apps/gnuradio-config-info.cc
index 19291f4dae..bccf99f8d9 100644
--- a/gnuradio-runtime/apps/gnuradio-config-info.cc
+++ b/gnuradio-runtime/apps/gnuradio-config-info.cc
@@ -42,11 +42,21 @@ main(int argc, char **argv)
("sysconfdir", "print gnuradio system configuration directory")
("prefsdir", "print gnuradio preferences directory")
("builddate", "print gnuradio build date (RFC2822 format)")
+ ("cc", "print gnuradio C compiler version")
+ ("cxx", "print gnuradio C++ compiler version")
+ ("cflags", "print gnuradio CFLAGS")
("version,v", "print gnuradio version")
;
- po::store(po::parse_command_line(argc, argv, desc), vm);
- po::notify(vm);
+ try {
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+ }
+ catch (po::error& error){
+ std::cerr << "Error: " << error.what() << std::endl << std::endl;
+ std::cerr << desc << std::endl;
+ return 1;
+ }
if(vm.size() == 0 || vm.count("help")) {
std::cout << desc << std::endl;
@@ -68,5 +78,14 @@ main(int argc, char **argv)
if(vm.count("version"))
std::cout << gr::version() << std::endl;
+ if(vm.count("cc"))
+ std::cout << gr::c_compiler() << std::endl;
+
+ if(vm.count("cxx"))
+ std::cout << gr::cxx_compiler() << std::endl;
+
+ if(vm.count("cflags"))
+ std::cout << gr::compiler_flags() << std::endl;
+
return 0;
}
diff --git a/gnuradio-runtime/include/gnuradio/constants.h b/gnuradio-runtime/include/gnuradio/constants.h
index beba6f2745..5e4a20f4ee 100644
--- a/gnuradio-runtime/include/gnuradio/constants.h
+++ b/gnuradio-runtime/include/gnuradio/constants.h
@@ -53,6 +53,21 @@ namespace gr {
*/
GR_RUNTIME_API const std::string version();
+ /*!
+ * \brief return C compiler used to build this version of GNU Radio
+ */
+ GR_RUNTIME_API const std::string c_compiler();
+
+ /*!
+ * \brief return C++ compiler used to build this version of GNU Radio
+ */
+ GR_RUNTIME_API const std::string cxx_compiler();
+
+ /*!
+ * \brief return C and C++ compiler flags used to build this version of GNU Radio
+ */
+ GR_RUNTIME_API const std::string compiler_flags();
+
} /* namespace gr */
#endif /* INCLUDED_GR_CONSTANTS_H */
diff --git a/gnuradio-runtime/lib/constants.cc.in b/gnuradio-runtime/lib/constants.cc.in
index 828c4397f7..7173c60792 100644
--- a/gnuradio-runtime/lib/constants.cc.in
+++ b/gnuradio-runtime/lib/constants.cc.in
@@ -58,4 +58,22 @@ namespace gr {
return "@VERSION@";
}
+ const std::string
+ c_compiler()
+ {
+ return "@cmake_c_compiler_version@";
+ }
+
+ const std::string
+ cxx_compiler()
+ {
+ return "@cmake_cxx_compiler_version@";
+ }
+
+ const std::string
+ compiler_flags()
+ {
+ return "@COMPILER_INFO@";
+ }
+
} /* namespace gr */
diff --git a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
index 053925bb3a..9d6f4dd718 100644
--- a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
+++ b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt
@@ -48,6 +48,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gnuradio-runtime/python/pmt/CMakeLists.txt b/gnuradio-runtime/python/pmt/CMakeLists.txt
index a9bf85a622..f4cba41d34 100644
--- a/gnuradio-runtime/python/pmt/CMakeLists.txt
+++ b/gnuradio-runtime/python/pmt/CMakeLists.txt
@@ -42,6 +42,6 @@ foreach(py_qa_test_file ${py_qa_test_files})
${CMAKE_BINARY_DIR}/gnuradio-runtime/swig
)
set(GR_TEST_TARGET_DEPS gnuradio-runtime)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-analog/python/analog/CMakeLists.txt b/gr-analog/python/analog/CMakeLists.txt
index 3c09709034..2da8273c6c 100644
--- a/gr-analog/python/analog/CMakeLists.txt
+++ b/gr-analog/python/analog/CMakeLists.txt
@@ -54,7 +54,7 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-atsc/python/atsc/CMakeLists.txt b/gr-atsc/python/atsc/CMakeLists.txt
index ab19b13e2d..a26df35424 100644
--- a/gr-atsc/python/atsc/CMakeLists.txt
+++ b/gr-atsc/python/atsc/CMakeLists.txt
@@ -58,6 +58,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-audio/python/audio/CMakeLists.txt b/gr-audio/python/audio/CMakeLists.txt
index 4764c6543d..11409e4323 100644
--- a/gr-audio/python/audio/CMakeLists.txt
+++ b/gr-audio/python/audio/CMakeLists.txt
@@ -42,6 +42,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-blocks/grc/blocks_block_tree.xml b/gr-blocks/grc/blocks_block_tree.xml
index 18e6a05213..e63128337d 100644
--- a/gr-blocks/grc/blocks_block_tree.xml
+++ b/gr-blocks/grc/blocks_block_tree.xml
@@ -120,6 +120,7 @@
<block>blocks_message_strobe</block>
<block>blocks_message_debug</block>
<block>blocks_pdu_to_tagged_stream</block>
+ <block>blocks_tagged_stream_multiply_length</block>
<block>blocks_tagged_stream_to_pdu</block>
<block>blocks_random_pdu</block>
</cat>
diff --git a/gr-blocks/grc/blocks_tagged_stream_multiply_length.xml b/gr-blocks/grc/blocks_tagged_stream_multiply_length.xml
new file mode 100644
index 0000000000..f4abb92903
--- /dev/null
+++ b/gr-blocks/grc/blocks_tagged_stream_multiply_length.xml
@@ -0,0 +1,70 @@
+<block>
+ <name>Tagged Stream Multiply Length Tag</name>
+ <key>blocks_tagged_stream_multiply_length</key>
+ <import>from gnuradio import blocks</import>
+ <make>blocks.tagged_stream_multiply_length($type.size*$vlen, $lengthtagname, $c)</make>
+ <callback>set_scalar($c)</callback>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:gr.sizeof_gr_complex</opt>
+ </option>
+ <option>
+ <name>Float</name>
+ <key>float</key>
+ <opt>size:gr.sizeof_float</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>int</key>
+ <opt>size:gr.sizeof_int</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>short</key>
+ <opt>size:gr.sizeof_short</opt>
+ </option>
+ <option>
+ <name>Byte</name>
+ <key>byte</key>
+ <opt>size:gr.sizeof_char</opt>
+ </option>
+ </param>
+ <param>
+ <name>Length tag names</name>
+ <key>lengthtagname</key>
+ <type>string</type>
+ </param>
+ <param>
+ <name>Vector Length</name>
+ <key>vlen</key>
+ <value>1</value>
+ <type>int</type>
+ </param>
+ <param>
+ <name>Length Scalar</name>
+ <key>c</key>
+ <value>1.0</value>
+ <type>real</type>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </sink>
+ <sink>
+ <name>set_scalar</name>
+ <type>message</type>
+ <optional>1</optional>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ <vlen>$vlen</vlen>
+ </source>
+</block>
+
diff --git a/gr-blocks/grc/blocks_tags_strobe.xml b/gr-blocks/grc/blocks_tags_strobe.xml
index 16109eaad1..f17edd2b99 100644
--- a/gr-blocks/grc/blocks_tags_strobe.xml
+++ b/gr-blocks/grc/blocks_tags_strobe.xml
@@ -9,8 +9,9 @@
<key>blocks_tags_strobe</key>
<import>from gnuradio import blocks</import>
<import>import pmt</import>
- <make>blocks.tags_strobe($type.size*$vlen, $value, $nsamps)</make>
+ <make>blocks.tags_strobe($type.size*$vlen, $value, $nsamps, $key)</make>
<callback>set_value($value)</callback>
+ <callback>set_key($key)</callback>
<callback>set_nsamps($nsamps)</callback>
<param>
<name>Output Type</name>
@@ -49,6 +50,12 @@
<type>raw</type>
</param>
<param>
+ <name>Key (PMT)</name>
+ <key>key</key>
+ <value>pmt.intern("strobe")</value>
+ <type>raw</type>
+ </param>
+ <param>
<name>Num. Samples</name>
<key>nsamps</key>
<value>1000</value>
diff --git a/gr-blocks/grc/blocks_throttle.xml b/gr-blocks/grc/blocks_throttle.xml
index 8293cbde9c..06f96b15cc 100644
--- a/gr-blocks/grc/blocks_throttle.xml
+++ b/gr-blocks/grc/blocks_throttle.xml
@@ -9,7 +9,7 @@
<key>blocks_throttle</key>
<throttle>1</throttle>
<import>from gnuradio import blocks</import>
- <make>blocks.throttle($type.size*$vlen, $samples_per_second)</make>
+ <make>blocks.throttle($type.size*$vlen, $samples_per_second,$ignoretag)</make>
<callback>set_sample_rate($samples_per_second)</callback>
<param>
<name>Type</name>
@@ -53,6 +53,12 @@
<value>1</value>
<type>int</type>
</param>
+ <param>
+ <name>Ignore rx_rate tag</name>
+ <key>ignoretag</key>
+ <value>True</value>
+ <type>bool</type>
+ </param>
<check>$vlen &gt; 0</check>
<sink>
<name>in</name>
diff --git a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt
index 83338b771d..90a32f386b 100644
--- a/gr-blocks/include/gnuradio/blocks/CMakeLists.txt
+++ b/gr-blocks/include/gnuradio/blocks/CMakeLists.txt
@@ -192,6 +192,7 @@ install(FILES
tag_gate.h
tagged_file_sink.h
tagged_stream_mux.h
+ tagged_stream_multiply_length.h
tagged_stream_to_pdu.h
tags_strobe.h
threshold_ff.h
diff --git a/gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h b/gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h
new file mode 100644
index 0000000000..de46516f24
--- /dev/null
+++ b/gr-blocks/include/gnuradio/blocks/tagged_stream_multiply_length.h
@@ -0,0 +1,60 @@
+/* -*- c++ -*- */
+/* Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_H
+#define INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_H
+
+#include <gnuradio/blocks/api.h>
+#include <gnuradio/tagged_stream_block.h>
+
+namespace gr {
+ namespace blocks {
+
+ /*!
+ * \brief Allows scaling of a tagged stream length tag
+ * \ingroup stream_operators_blk
+ *
+ * \details
+ * Searches for a specific tagged stream length tag and multiplies
+ * that length by a constant - for constant rate change blocks
+ * in a tagged stream
+ */
+ class BLOCKS_API tagged_stream_multiply_length : virtual public block
+ {
+ public:
+ typedef boost::shared_ptr<tagged_stream_multiply_length> sptr;
+ virtual void set_scalar(double scalar) = 0;
+
+ /*!
+ * Make a tagged stream multiply_length block.
+ *
+ * \param itemsize Items size (number of bytes per item)
+ * \param lengthtagname Length tag key
+ * \param scalar value to scale length tag values by
+ */
+ static sptr make(size_t itemsize, const std::string &lengthtagname, double scalar);
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif /* INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_H */
+
diff --git a/gr-blocks/include/gnuradio/blocks/tags_strobe.h b/gr-blocks/include/gnuradio/blocks/tags_strobe.h
index 3660ca4c1b..eb04f01415 100644
--- a/gr-blocks/include/gnuradio/blocks/tags_strobe.h
+++ b/gr-blocks/include/gnuradio/blocks/tags_strobe.h
@@ -54,9 +54,10 @@ namespace gr {
* \param sizeof_stream_item size of the stream items in bytes.
* \param value The value of the tags to send, as a PMT.
* \param nsamps the number of samples between each tag.
+ * \param key The tag key to sent
*/
static sptr make(size_t sizeof_stream_item,
- pmt::pmt_t value, uint64_t nsamps);
+ pmt::pmt_t value, uint64_t nsamps, pmt::pmt_t key = pmt::intern("strobe"));
/*!
* Reset the value of the tags being sent.
@@ -65,11 +66,21 @@ namespace gr {
virtual void set_value(pmt::pmt_t value) = 0;
/*!
+ * Change the tag key we are sending
+ */
+ virtual void set_key(pmt::pmt_t key) = 0;
+
+ /*!
* Get the value of the tags being sent.
*/
virtual pmt::pmt_t value() const = 0;
/*!
+ * Get the key of the tags being sent.
+ */
+ virtual pmt::pmt_t key() const = 0;
+
+ /*!
* Reset the sending interval.
* \param nsamps the number of samples between each tag
*/
@@ -79,6 +90,7 @@ namespace gr {
* Get the number of samples between the tag strobe.
*/
virtual uint64_t nsamps() const = 0;
+
};
} /* namespace blocks */
diff --git a/gr-blocks/include/gnuradio/blocks/throttle.h b/gr-blocks/include/gnuradio/blocks/throttle.h
index 662582e0ba..fa38eae09c 100644
--- a/gr-blocks/include/gnuradio/blocks/throttle.h
+++ b/gr-blocks/include/gnuradio/blocks/throttle.h
@@ -48,7 +48,7 @@ namespace gr {
public:
typedef boost::shared_ptr<throttle> sptr;
- static sptr make(size_t itemsize, double samples_per_sec);
+ static sptr make(size_t itemsize, double samples_per_sec, bool ignore_tags=true);
//! Sets the sample rate in samples per second.
virtual void set_sample_rate(double rate) = 0;
diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt
index 6eded4a273..ab6c7e95be 100644
--- a/gr-blocks/lib/CMakeLists.txt
+++ b/gr-blocks/lib/CMakeLists.txt
@@ -232,6 +232,7 @@ list(APPEND gr_blocks_sources
stretch_ff_impl.cc
tagged_file_sink_impl.cc
tagged_stream_to_pdu_impl.cc
+ tagged_stream_multiply_length_impl.cc
tags_strobe_impl.cc
threshold_ff_impl.cc
throttle_impl.cc
diff --git a/gr-blocks/lib/add_ff_impl.cc b/gr-blocks/lib/add_ff_impl.cc
index e12e86c061..ca2fbe659c 100644
--- a/gr-blocks/lib/add_ff_impl.cc
+++ b/gr-blocks/lib/add_ff_impl.cc
@@ -56,14 +56,8 @@ namespace gr {
int noi = d_vlen*noutput_items;
memcpy(out, input_items[0], noi*sizeof(float));
- if(is_unaligned()) {
- for(size_t i = 1; i < input_items.size(); i++)
- volk_32f_x2_add_32f_u(out, out, (const float*)input_items[i], noi);
- }
- else {
- for(size_t i = 1; i < input_items.size(); i++)
- volk_32f_x2_add_32f_a(out, out, (const float*)input_items[i], noi);
- }
+ for(size_t i = 1; i < input_items.size(); i++)
+ volk_32f_x2_add_32f(out, out, (const float*)input_items[i], noi);
return noutput_items;
}
diff --git a/gr-blocks/lib/conjugate_cc_impl.cc b/gr-blocks/lib/conjugate_cc_impl.cc
index 14fbbf172c..55ff30aa5d 100644
--- a/gr-blocks/lib/conjugate_cc_impl.cc
+++ b/gr-blocks/lib/conjugate_cc_impl.cc
@@ -54,12 +54,7 @@ namespace gr {
gr_complex *iptr = (gr_complex *) input_items[0];
gr_complex *optr = (gr_complex *) output_items[0];
- if(is_unaligned()) {
- volk_32fc_conjugate_32fc_u(optr, iptr, noutput_items);
- }
- else {
- volk_32fc_conjugate_32fc_a(optr, iptr, noutput_items);
- }
+ volk_32fc_conjugate_32fc(optr, iptr, noutput_items);
return noutput_items;
}
diff --git a/gr-blocks/lib/endian_swap_impl.cc b/gr-blocks/lib/endian_swap_impl.cc
index 3c263e40a3..604e8b9ad8 100644
--- a/gr-blocks/lib/endian_swap_impl.cc
+++ b/gr-blocks/lib/endian_swap_impl.cc
@@ -60,47 +60,24 @@ namespace gr {
char *out = (char*)output_items[0];
int nbytes(output_signature()->sizeof_stream_item(0));
- if(is_unaligned()) {
- switch(nbytes){
- case 1:
- memcpy(out,in,noutput_items);
- break;
- case 2:
- memcpy(out,in,2*noutput_items);
- volk_16u_byteswap_u((uint16_t*)out,noutput_items);
- break;
- case 4:
- memcpy(out,in,4*noutput_items);
- volk_32u_byteswap_u((uint32_t*)out,noutput_items);
- break;
- case 8:
- memcpy(out,in,8*noutput_items);
- volk_64u_byteswap_u((uint64_t*)out,noutput_items);
- break;
- default:
- throw std::runtime_error("itemsize is not valid for endian_swap!");
- }
- }
- else {
- switch(nbytes) {
- case 1:
- memcpy(out,in,noutput_items);
- break;
- case 2:
- memcpy(out,in,2*noutput_items);
- volk_16u_byteswap_a((uint16_t*)out,noutput_items);
- break;
- case 4:
- memcpy(out,in,4*noutput_items);
- volk_32u_byteswap_a((uint32_t*)out,noutput_items);
- break;
- case 8:
- memcpy(out,in,8*noutput_items);
- volk_64u_byteswap_a((uint64_t*)out,noutput_items);
- break;
- default:
- throw std::runtime_error("itemsize is not valid for endian_swap!");
- }
+ switch(nbytes){
+ case 1:
+ memcpy(out,in,noutput_items);
+ break;
+ case 2:
+ memcpy(out,in,2*noutput_items);
+ volk_16u_byteswap((uint16_t*)out,noutput_items);
+ break;
+ case 4:
+ memcpy(out,in,4*noutput_items);
+ volk_32u_byteswap((uint32_t*)out,noutput_items);
+ break;
+ case 8:
+ memcpy(out,in,8*noutput_items);
+ volk_64u_byteswap((uint64_t*)out,noutput_items);
+ break;
+ default:
+ throw std::runtime_error("itemsize is not valid for endian_swap!");
}
return noutput_items;
diff --git a/gr-blocks/lib/multiply_cc_impl.cc b/gr-blocks/lib/multiply_cc_impl.cc
index b54296c112..2e1ce93b37 100644
--- a/gr-blocks/lib/multiply_cc_impl.cc
+++ b/gr-blocks/lib/multiply_cc_impl.cc
@@ -56,14 +56,9 @@ namespace gr {
int noi = d_vlen*noutput_items;
memcpy(out, input_items[0], noi*sizeof(gr_complex));
- if(is_unaligned()) {
- for(size_t i = 1; i < input_items.size(); i++)
- volk_32fc_x2_multiply_32fc_u(out, out, (gr_complex*)input_items[i], noi);
- }
- else {
- for(size_t i = 1; i < input_items.size(); i++)
- volk_32fc_x2_multiply_32fc_a(out, out, (gr_complex*)input_items[i], noi);
- }
+ for(size_t i = 1; i < input_items.size(); i++)
+ volk_32fc_x2_multiply_32fc(out, out, (gr_complex*)input_items[i], noi);
+
return noutput_items;
}
diff --git a/gr-blocks/lib/multiply_conjugate_cc_impl.cc b/gr-blocks/lib/multiply_conjugate_cc_impl.cc
index 671e1160f6..7f9652152b 100644
--- a/gr-blocks/lib/multiply_conjugate_cc_impl.cc
+++ b/gr-blocks/lib/multiply_conjugate_cc_impl.cc
@@ -57,12 +57,7 @@ namespace gr {
gr_complex *out = (gr_complex *) output_items[0];
int noi = d_vlen*noutput_items;
- if(is_unaligned()) {
- volk_32fc_x2_multiply_conjugate_32fc_u(out, in0, in1, noi);
- }
- else {
- volk_32fc_x2_multiply_conjugate_32fc_a(out, in0, in1, noi);
- }
+ volk_32fc_x2_multiply_conjugate_32fc(out, in0, in1, noi);
return noutput_items;
}
diff --git a/gr-blocks/lib/multiply_const_cc_impl.cc b/gr-blocks/lib/multiply_const_cc_impl.cc
index d0393907b0..f6b8dc3d63 100644
--- a/gr-blocks/lib/multiply_const_cc_impl.cc
+++ b/gr-blocks/lib/multiply_const_cc_impl.cc
@@ -58,12 +58,7 @@ namespace gr {
gr_complex *out = (gr_complex *) output_items[0];
int noi = d_vlen*noutput_items;
- if(is_unaligned()) {
- volk_32fc_s32fc_multiply_32fc_u(out, in, d_k, noi);
- }
- else {
- volk_32fc_s32fc_multiply_32fc_a(out, in, d_k, noi);
- }
+ volk_32fc_s32fc_multiply_32fc(out, in, d_k, noi);
return noutput_items;
}
diff --git a/gr-blocks/lib/multiply_const_ff_impl.cc b/gr-blocks/lib/multiply_const_ff_impl.cc
index 67205c06c0..366c06181f 100644
--- a/gr-blocks/lib/multiply_const_ff_impl.cc
+++ b/gr-blocks/lib/multiply_const_ff_impl.cc
@@ -58,12 +58,7 @@ namespace gr {
float *out = (float *) output_items[0];
int noi = d_vlen*noutput_items;
- if(is_unaligned()) {
- volk_32f_s32f_multiply_32f_u(out, in, d_k, noi);
- }
- else {
- volk_32f_s32f_multiply_32f_a(out, in, d_k, noi);
- }
+ volk_32f_s32f_multiply_32f(out, in, d_k, noi);
return noutput_items;
}
diff --git a/gr-blocks/lib/multiply_ff_impl.cc b/gr-blocks/lib/multiply_ff_impl.cc
index 912c1bb926..22100497c5 100644
--- a/gr-blocks/lib/multiply_ff_impl.cc
+++ b/gr-blocks/lib/multiply_ff_impl.cc
@@ -56,14 +56,9 @@ namespace gr {
int noi = d_vlen*noutput_items;
memcpy(out, input_items[0], noi*sizeof(float));
- if(is_unaligned()) {
- for(size_t i = 1; i < input_items.size(); i++)
- volk_32f_x2_multiply_32f_u(out, out, (float*)input_items[i], noi);
- }
- else {
- for(size_t i = 1; i < input_items.size(); i++)
- volk_32f_x2_multiply_32f_a(out, out, (float*)input_items[i], noi);
- }
+ for(size_t i = 1; i < input_items.size(); i++)
+ volk_32f_x2_multiply_32f(out, out, (float*)input_items[i], noi);
+
return noutput_items;
}
diff --git a/gr-blocks/lib/tagged_stream_multiply_length_impl.cc b/gr-blocks/lib/tagged_stream_multiply_length_impl.cc
new file mode 100644
index 0000000000..18a8eef1e9
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_multiply_length_impl.cc
@@ -0,0 +1,89 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "tagged_stream_multiply_length_impl.h"
+
+namespace gr {
+ namespace blocks {
+
+ tagged_stream_multiply_length::sptr
+ tagged_stream_multiply_length::make(size_t itemsize, const std::string &lengthtagname, double scalar)
+ {
+ return gnuradio::get_initial_sptr (new tagged_stream_multiply_length_impl(itemsize, lengthtagname, scalar));
+ }
+
+ tagged_stream_multiply_length_impl::tagged_stream_multiply_length_impl(size_t itemsize, const std::string &lengthtagname, double scalar)
+ : block("tagged_stream_multiply_length",
+ io_signature::make(1, 1, itemsize),
+ io_signature::make(1, 1, itemsize)),
+ d_lengthtag(pmt::mp(lengthtagname)),
+ d_scalar(scalar),
+ d_itemsize(itemsize)
+ {
+ set_tag_propagation_policy(TPP_DONT);
+ set_relative_rate(1);
+ message_port_register_in(pmt::intern("set_scalar"));
+ set_msg_handler(pmt::intern("set_scalar"),
+ boost::bind(&tagged_stream_multiply_length_impl::set_scalar_pmt, this, _1));
+ }
+
+ tagged_stream_multiply_length_impl::~tagged_stream_multiply_length_impl()
+ {
+ }
+
+ int
+ tagged_stream_multiply_length_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 void* in = input_items[0];
+ void* out = output_items[0];
+
+ // move data across ( wasteful memcopy :< )
+ memcpy(out, in, noutput_items*d_itemsize);
+
+ // move and update tags
+ std::vector<tag_t> tags;
+ get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+ninput_items[0]);
+ for(size_t i=0; i<tags.size(); i++){
+ if(pmt::eqv( tags[i].key , d_lengthtag)){
+ // propagate with value update (scaled)
+ add_item_tag(0, tags[i].offset, tags[i].key, pmt::from_long(pmt::to_long(tags[i].value) * d_scalar), tags[i].srcid );
+ } else {
+ // propagate unmodified
+ add_item_tag(0, tags[i].offset, tags[i].key, tags[i].value, tags[i].srcid );
+ }
+ }
+
+ consume_each(noutput_items);
+ return noutput_items;
+ }
+
+ } /* namespace blocks */
+} /* namespace gr */
+
diff --git a/gr-blocks/lib/tagged_stream_multiply_length_impl.h b/gr-blocks/lib/tagged_stream_multiply_length_impl.h
new file mode 100644
index 0000000000..5d61650369
--- /dev/null
+++ b/gr-blocks/lib/tagged_stream_multiply_length_impl.h
@@ -0,0 +1,62 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_IMPL_H
+#define INCLUDED_TAGGED_STREAM_MULTIPLY_LENGTH_IMPL_H
+
+#include <vector>
+#include <gnuradio/blocks/tagged_stream_multiply_length.h>
+
+namespace gr {
+ namespace blocks {
+
+ class tagged_stream_multiply_length_impl : public tagged_stream_multiply_length
+ {
+ private:
+ pmt::pmt_t d_lengthtag;
+ double d_scalar;
+ size_t d_itemsize;
+
+ public:
+ tagged_stream_multiply_length_impl(size_t itemsize, const std::string &lengthtagname, double scalar);
+ ~tagged_stream_multiply_length_impl();
+
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+
+ void set_scalar(double scalar){
+ d_scalar = scalar;
+ }
+
+ void set_scalar_pmt(pmt::pmt_t msg){
+ set_scalar(pmt::to_double(msg));
+ }
+
+ };
+
+ } // namespace blocks
+} // namespace gr
+
+#endif
+
diff --git a/gr-blocks/lib/tags_strobe_impl.cc b/gr-blocks/lib/tags_strobe_impl.cc
index 41329d88a3..cfe335781c 100644
--- a/gr-blocks/lib/tags_strobe_impl.cc
+++ b/gr-blocks/lib/tags_strobe_impl.cc
@@ -40,20 +40,25 @@ namespace gr {
tags_strobe::sptr
tags_strobe::make(size_t sizeof_stream_item,
- pmt::pmt_t value, uint64_t nsamps)
+ pmt::pmt_t value, uint64_t nsamps, pmt::pmt_t key)
{
return gnuradio::get_initial_sptr
- (new tags_strobe_impl(sizeof_stream_item, value, nsamps));
+ (new tags_strobe_impl(sizeof_stream_item, value, nsamps, key));
}
tags_strobe_impl::tags_strobe_impl(size_t sizeof_stream_item,
- pmt::pmt_t value, uint64_t nsamps)
+ pmt::pmt_t value, uint64_t nsamps,
+ pmt::pmt_t key)
: sync_block("tags_strobe",
io_signature::make(0, 0, 0),
io_signature::make(1, 1, sizeof_stream_item)),
d_itemsize(sizeof_stream_item)
{
+ d_tag.offset = 0;
+ d_tag.key = pmt::intern("strobe");
+ d_tag.srcid = alias_pmt();
set_value(value);
+ set_key(key);
set_nsamps(nsamps);
}
@@ -64,10 +69,13 @@ namespace gr {
void
tags_strobe_impl::set_value(pmt::pmt_t value)
{
- d_tag.offset = 0;
- d_tag.key = pmt::intern("strobe");
d_tag.value = value;
- d_tag.srcid = alias_pmt();
+ }
+
+ void
+ tags_strobe_impl::set_key(pmt::pmt_t key)
+ {
+ d_tag.key = key;
}
void
diff --git a/gr-blocks/lib/tags_strobe_impl.h b/gr-blocks/lib/tags_strobe_impl.h
index a6d73cfead..e99d3e1b44 100644
--- a/gr-blocks/lib/tags_strobe_impl.h
+++ b/gr-blocks/lib/tags_strobe_impl.h
@@ -40,11 +40,14 @@ namespace gr {
public:
tags_strobe_impl(size_t sizeof_stream_item,
- pmt::pmt_t value, uint64_t nsamps);
+ pmt::pmt_t value, uint64_t nsamps,
+ pmt::pmt_t key);
~tags_strobe_impl();
void set_value(pmt::pmt_t value);
+ void set_key(pmt::pmt_t key);
pmt::pmt_t value() const { return d_tag.value; }
+ pmt::pmt_t key() const { return d_tag.key; }
void set_nsamps(uint64_t nsamps);
uint64_t nsamps() const { return d_nsamps; }
diff --git a/gr-blocks/lib/throttle_impl.cc b/gr-blocks/lib/throttle_impl.cc
index 42f3665c86..f46decee11 100644
--- a/gr-blocks/lib/throttle_impl.cc
+++ b/gr-blocks/lib/throttle_impl.cc
@@ -29,22 +29,26 @@
#include <cstring>
#include <boost/thread/thread.hpp>
+pmt::pmt_t throttle_rx_rate_pmt(pmt::intern("rx_rate"));
+
namespace gr {
namespace blocks {
throttle::sptr
- throttle::make(size_t itemsize, double samples_per_sec)
+ throttle::make(size_t itemsize, double samples_per_sec, bool ignore_tags)
{
return gnuradio::get_initial_sptr
- (new throttle_impl(itemsize, samples_per_sec));
+ (new throttle_impl(itemsize, samples_per_sec, ignore_tags));
}
throttle_impl::throttle_impl(size_t itemsize,
- double samples_per_second)
+ double samples_per_second,
+ bool ignore_tags)
: sync_block("throttle",
io_signature::make(1, 1, itemsize),
io_signature::make(1, 1, itemsize)),
- d_itemsize(itemsize)
+ d_itemsize(itemsize),
+ d_ignore_tags(ignore_tags)
{
set_sample_rate(samples_per_second);
}
@@ -74,6 +78,20 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
+ // check for updated rx_rate tag
+ if(!d_ignore_tags){
+ uint64_t abs_N = nitems_read(0);
+ std::vector<tag_t> all_tags;
+ get_tags_in_range(all_tags, 0, abs_N, abs_N + noutput_items);
+ std::vector<tag_t>::iterator itr;
+ for(itr = all_tags.begin(); itr != all_tags.end(); itr++) {
+ if(pmt::eq( (*itr).key, throttle_rx_rate_pmt)){
+ double new_rate = pmt::to_double( (*itr).value );
+ set_sample_rate(new_rate);
+ }
+ }
+ }
+
//calculate the expected number of samples to have passed through
boost::system_time now = boost::get_system_time();
boost::int64_t ticks = (now - d_start).ticks();
diff --git a/gr-blocks/lib/throttle_impl.h b/gr-blocks/lib/throttle_impl.h
index 797cb7d942..c5e43d7564 100644
--- a/gr-blocks/lib/throttle_impl.h
+++ b/gr-blocks/lib/throttle_impl.h
@@ -35,9 +35,10 @@ namespace gr {
size_t d_itemsize;
uint64_t d_total_samples;
double d_samps_per_tick, d_samps_per_us;
+ bool d_ignore_tags;
public:
- throttle_impl(size_t itemsize, double samples_per_sec);
+ throttle_impl(size_t itemsize, double samples_per_sec, bool ignore_tags=true);
~throttle_impl();
void setup_rpc();
diff --git a/gr-blocks/python/blocks/CMakeLists.txt b/gr-blocks/python/blocks/CMakeLists.txt
index 9050eff6c2..9287975730 100644
--- a/gr-blocks/python/blocks/CMakeLists.txt
+++ b/gr-blocks/python/blocks/CMakeLists.txt
@@ -54,7 +54,7 @@ if(ENABLE_TESTING)
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-blocks/swig/blocks_swig5.i b/gr-blocks/swig/blocks_swig5.i
index 09679531d9..deb3b5a045 100644
--- a/gr-blocks/swig/blocks_swig5.i
+++ b/gr-blocks/swig/blocks_swig5.i
@@ -51,6 +51,7 @@
#include "gnuradio/blocks/sub_cc.h"
#include "gnuradio/blocks/tag_gate.h"
#include "gnuradio/blocks/tagged_stream_mux.h"
+#include "gnuradio/blocks/tagged_stream_multiply_length.h"
#include "gnuradio/blocks/tagged_stream_to_pdu.h"
#include "gnuradio/blocks/tags_strobe.h"
#include "gnuradio/blocks/threshold_ff.h"
@@ -90,6 +91,7 @@
%include "gnuradio/blocks/sub_cc.h"
%include "gnuradio/blocks/tag_gate.h"
%include "gnuradio/blocks/tagged_stream_mux.h"
+%include "gnuradio/blocks/tagged_stream_multiply_length.h"
%include "gnuradio/blocks/tagged_stream_to_pdu.h"
%include "gnuradio/blocks/tags_strobe.h"
%include "gnuradio/blocks/threshold_ff.h"
@@ -128,6 +130,7 @@ GR_SWIG_BLOCK_MAGIC2(blocks, sub_ii);
GR_SWIG_BLOCK_MAGIC2(blocks, sub_cc);
GR_SWIG_BLOCK_MAGIC2(blocks, tag_gate);
GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_mux);
+GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_multiply_length);
GR_SWIG_BLOCK_MAGIC2(blocks, tagged_stream_to_pdu);
GR_SWIG_BLOCK_MAGIC2(blocks, tags_strobe);
GR_SWIG_BLOCK_MAGIC2(blocks, threshold_ff);
diff --git a/gr-channels/python/channels/CMakeLists.txt b/gr-channels/python/channels/CMakeLists.txt
index 1f6f08bb69..0e36b94a90 100644
--- a/gr-channels/python/channels/CMakeLists.txt
+++ b/gr-channels/python/channels/CMakeLists.txt
@@ -51,6 +51,6 @@ if(ENABLE_TESTING)
file (GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-comedi/python/comedi/CMakeLists.txt b/gr-comedi/python/comedi/CMakeLists.txt
index 081edd917a..5ac692f995 100644
--- a/gr-comedi/python/comedi/CMakeLists.txt
+++ b/gr-comedi/python/comedi/CMakeLists.txt
@@ -44,6 +44,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-digital/lib/constellation.cc b/gr-digital/lib/constellation.cc
index aab00f0cd3..7d2c170d34 100644
--- a/gr-digital/lib/constellation.cc
+++ b/gr-digital/lib/constellation.cc
@@ -273,6 +273,7 @@ namespace gr {
std::vector<float> s(k, 0);
float scale = d_scalefactor*d_scalefactor;
+ int v;
for(int i = 0; i < M; i++) {
// Calculate the distance between the sample and the current
@@ -283,10 +284,15 @@ namespace gr {
// the scaled noise power.
float d = expf(-dist / (2.0*npwr*scale));
+ if(d_apply_pre_diff_code)
+ v = d_pre_diff_code[i];
+ else
+ v = i;
+
for(int j = 0; j < k; j++) {
// Get the bit at the jth index
int mask = 1 << j;
- int bit = (d_pre_diff_code[i] & mask) >> j;
+ int bit = (v & mask) >> j;
// If the bit is a 0, add to the probability of a zero
if(bit == 0)
diff --git a/gr-digital/python/digital/CMakeLists.txt b/gr-digital/python/digital/CMakeLists.txt
index e0cb77fb21..091bd883b3 100644
--- a/gr-digital/python/digital/CMakeLists.txt
+++ b/gr-digital/python/digital/CMakeLists.txt
@@ -80,6 +80,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-fcd/python/fcd/CMakeLists.txt b/gr-fcd/python/fcd/CMakeLists.txt
index 468dd7dd3a..78ae54bd94 100644
--- a/gr-fcd/python/fcd/CMakeLists.txt
+++ b/gr-fcd/python/fcd/CMakeLists.txt
@@ -42,6 +42,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-fec/python/fec/CMakeLists.txt b/gr-fec/python/fec/CMakeLists.txt
index a05981c8e6..a7eefaa0c1 100644
--- a/gr-fec/python/fec/CMakeLists.txt
+++ b/gr-fec/python/fec/CMakeLists.txt
@@ -45,6 +45,6 @@ include(GrTest)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-fft/include/gnuradio/fft/window.h b/gr-fft/include/gnuradio/fft/window.h
index 4a7fb44ff9..92f62c64cb 100644
--- a/gr-fft/include/gnuradio/fft/window.h
+++ b/gr-fft/include/gnuradio/fft/window.h
@@ -35,19 +35,41 @@ namespace gr {
public:
enum win_type {
- WIN_NONE = -1, //!< don't use a window
- WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB
- WIN_HANN = 1, //!< Hann window; max attenuation 44 dB
- WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB
- WIN_RECTANGULAR = 3, //!< Basic rectangular window
- WIN_KAISER = 4, //!< Kaiser window; max attenuation a function of beta, google it
- WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window
- WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency
- WIN_BARTLETT = 6, //!< Barlett (triangular) window
- WIN_FLATTOP = 7, //!< flat top window; useful in FFTs
+ WIN_HAMMING = 0, //!< Hamming window; max attenuation 53 dB
+ WIN_HANN = 1, //!< Hann window; max attenuation 44 dB
+ WIN_BLACKMAN = 2, //!< Blackman window; max attenuation 74 dB
+ WIN_RECTANGULAR = 3, //!< Basic rectangular window; max attenuation 21 dB
+ WIN_KAISER = 4, //!< Kaiser window; max attenuation see window::max_attenuation
+ WIN_BLACKMAN_hARRIS = 5, //!< Blackman-harris window; max attenuation 92 dB
+ WIN_BLACKMAN_HARRIS = 5, //!< alias to WIN_BLACKMAN_hARRIS for capitalization consistency
+ WIN_BARTLETT = 6, //!< Barlett (triangular) window; max attenuation 26 dB
+ WIN_FLATTOP = 7, //!< flat top window; useful in FFTs; max attenuation 93 dB
};
/*!
+ * \brief Given a window::win_type, this tells you the maximum
+ * attenuation you can expect.
+ *
+ * \details
+ * For most windows, this is a set value. For the Kaiser window,
+ * the attenuation is based on the value of beta. The actual
+ * relationship is a piece-wise exponential relationship to
+ * calculate beta from the desired attenuation and can be found
+ * on page 542 of Oppenheim and Schafer (Discrete-Time Signal
+ * Processing, 3rd edition). To simplify this function to solve
+ * for A given beta, we use a linear form that is exact for
+ * attenuation >= 50 dB.
+ *
+ * For an attenuation of 50 dB, beta = 4.55.
+ *
+ * For an attenuation of 70 dB, beta = 6.76.
+ *
+ * \param type The window::win_type enumeration of the window type.
+ * \param beta Beta value only used for the Kaiser window.
+ */
+ static double max_attenuation(win_type type, double beta=6.76);
+
+ /*!
* \brief Helper function to build cosine-based windows. 3-coefficient version.
*/
static std::vector<float> coswindow(int ntaps, float c0, float c1, float c2);
diff --git a/gr-fft/lib/window.cc b/gr-fft/lib/window.cc
index 1610b46f5d..015e2d9943 100644
--- a/gr-fft/lib/window.cc
+++ b/gr-fft/lib/window.cc
@@ -74,7 +74,24 @@ namespace gr {
return 1.0/(ntaps >> 1);
}
- std::vector<float>
+ double
+ window::max_attenuation(win_type type, double beta)
+ {
+ switch(type) {
+ case(WIN_HAMMING): return 53; break;
+ case(WIN_HANN): return 44; break;
+ case(WIN_BLACKMAN): return 74; break;
+ case(WIN_RECTANGULAR): return 21; break;
+ case(WIN_KAISER): return (beta/0.1102 + 8.7); break;
+ case(WIN_BLACKMAN_hARRIS): return 92; break;
+ case(WIN_BARTLETT): return 27; break;
+ case(WIN_FLATTOP): return 93; break;
+ default:
+ throw std::out_of_range("window::max_attenuation: unknown window type provided.");
+ }
+ }
+
+ std::vector<float>
window::coswindow(int ntaps, float c0, float c1, float c2)
{
std::vector<float> taps(ntaps);
diff --git a/gr-fft/python/fft/CMakeLists.txt b/gr-fft/python/fft/CMakeLists.txt
index e0bc19124d..b5a8c9d4f7 100644
--- a/gr-fft/python/fft/CMakeLists.txt
+++ b/gr-fft/python/fft/CMakeLists.txt
@@ -41,6 +41,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-filter/doc/filter.dox b/gr-filter/doc/filter.dox
index ad0cfcb6c5..a9b329836c 100644
--- a/gr-filter/doc/filter.dox
+++ b/gr-filter/doc/filter.dox
@@ -54,11 +54,6 @@ impulse response (IIR) filtering.
an IIR filter with a single pole (also known as a moving average
filter).
-\li Adaptive FIR filters (see adaptive_fir.h): FIR filters that define
-an \b error and \b update_tap virtual interface to create filters that
-update the taps based on some criteria. \sa
-gr::digital::lms_dd_equalizer_cc, gr::digital::cma_equalizer_cc
-
\li PFB arbitrary resampler (see pfb_arb_resampler.h): performs
arbitrary resampling (i.e., using any real number) using the polyphase
filterbank method. \sa \ref pfb_arb_resampl
@@ -94,11 +89,6 @@ blocks.
<li>gr::filter::single_pole_iir_filter_cc</li>
<li>gr::filter::single_pole_iir_filter_ff</li>
</ul>
-<li>Adaptive FIR Filters</li>
- <ul>
- <li>gr::filter::adaptive_fir_ccc</li>
- <li>gr::filter::adaptive_fir_ccf</li>
- </ul>
<li>Polyphase Filterbanks</li>
<ul>
<li>gr::filter::pfb_arb_resampler_ccf</li>
diff --git a/gr-filter/grc/filter_pfb_decimator.xml b/gr-filter/grc/filter_pfb_decimator.xml
index 8ecf9b2d95..d57119636c 100644
--- a/gr-filter/grc/filter_pfb_decimator.xml
+++ b/gr-filter/grc/filter_pfb_decimator.xml
@@ -15,7 +15,8 @@
$channel,
$atten)
</make>
- <callback>set_taps($taps)</callback>
+ <callback>set_taps($taps)</callback>
+ <callback>set_channel(int($channel))</callback>
<param>
<name>Decimation</name>
<key>decim</key>
diff --git a/gr-filter/include/gnuradio/filter/CMakeLists.txt b/gr-filter/include/gnuradio/filter/CMakeLists.txt
index 7871c8c003..3135688eb4 100644
--- a/gr-filter/include/gnuradio/filter/CMakeLists.txt
+++ b/gr-filter/include/gnuradio/filter/CMakeLists.txt
@@ -79,7 +79,6 @@ add_custom_target(filter_generated_includes DEPENDS
install(FILES
${generated_includes}
api.h
- adaptive_fir.h
firdes.h
fir_filter.h
fir_filter_with_buffer.h
@@ -91,8 +90,6 @@ install(FILES
pm_remez.h
polyphase_filterbank.h
single_pole_iir.h
- adaptive_fir_ccc.h
- adaptive_fir_ccf.h
dc_blocker_cc.h
dc_blocker_ff.h
filter_delay_fc.h
diff --git a/gr-filter/include/gnuradio/filter/adaptive_fir.h b/gr-filter/include/gnuradio/filter/adaptive_fir.h
deleted file mode 100644
index be2060537f..0000000000
--- a/gr-filter/include/gnuradio/filter/adaptive_fir.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_H
-#define INCLUDED_FILTER_ADAPTIVE_FIR_H
-
-#include <gnuradio/filter/api.h>
-#include <gnuradio/filter/fir_filter.h>
-
-namespace gr {
- namespace filter {
- namespace kernel {
-
- /*!
- * \brief Adaptive FIR filter kernel with gr_complex input,
- * gr_complex output and gr_complex taps
- *
- * This class implements an adaptive FIR filter. Any class
- * actually wanting to use adaptive FIRs will contain an object of
- * this class.
- */
- class FILTER_API adaptive_fir_ccc : public fir_filter_ccc
- {
- public:
- adaptive_fir_ccc(int decimation,
- const std::vector<gr_complex> &taps);
- ~adaptive_fir_ccc();
-
- protected:
- // Override to calculate error signal per output
- virtual gr_complex error(const gr_complex &out) = 0;
-
- // Override to calculate new weight from old, corresponding input
- virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0;
-
- gr_complex d_error;
- };
-
-
- /*!
- * \brief Adaptive FIR filter kernel with gr_complex input,
- * gr_complex output and float taps
- *
- * This class implements an adaptive FIR filter. Any class
- * actually wanting to use adaptive FIRs will contain an object of
- * this class.
- */
- class FILTER_API adaptive_fir_ccf : public fir_filter_ccf
- {
- public:
- adaptive_fir_ccf(int decimation,
- const std::vector<float> &taps);
- ~adaptive_fir_ccf();
-
- protected:
- // Override to calculate error signal per output
- virtual float error(const gr_complex &out) = 0;
-
- // Override to calculate new weight from old, corresponding input
- virtual void update_tap(float &tap, const gr_complex &in) = 0;
-
- float d_error;
- };
-
- } /* namespace kernel */
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_H */
diff --git a/gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h b/gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h
deleted file mode 100644
index 13e05a477b..0000000000
--- a/gr-filter/include/gnuradio/filter/adaptive_fir_ccc.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H
-#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H
-
-#include <gnuradio/filter/api.h>
-#include <gnuradio/sync_decimator.h>
-
-namespace gr {
- namespace filter {
-
- /*!
- * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps
- * \ingroup filter_blk
- *
- * \details
- * This is a base class to implement an adaptive FIR
- * filter. Generally, another block will inherit from this one to
- * build a new type of adaptive filter such as an equalizer.
- *
- * This class implements two functions that are designed to be
- * overloaded by the child class: error(gr_complex out) and
- * update_tap(gr_complex tap, gr_complex in).
- *
- * The error() function calculates the error value that will be
- * used to adjust the taps. The update_tap function then uses the
- * error and the input signal value to update a particular
- * tap. Typically, the error is calculated for a given output and
- * then this is used in a loop to update all of the filter taps in
- * a loop:
- *
- * \code
- * d_error = error(sum);
- * for(k = 0; k < l; k++) {
- * update_tap(d_taps[ntaps-k-1], in[i+k]);
- * }
- * \endcode
- *
- * See digital::cma_equalizer_cc and digital::lms_dd_equalizer_cc
- * for example usage.
- */
- class FILTER_API adaptive_fir_ccc : virtual public sync_decimator
- {
- protected:
-
- public:
- // gr::filter::adaptive_fir_ccc::sptr
- typedef boost::shared_ptr<adaptive_fir_ccc> sptr;
-
- /*!
- * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps
- *
- * \param name Provides a name to identify this type of algorithm
- * \param decimation (interger) decimation rate of the filter
- * \param taps (complex) filter taps
- */
- static sptr make(const char *name, int decimation,
- const std::vector<gr_complex> &taps);
-
- virtual void set_taps(const std::vector<gr_complex> &taps) = 0;
- virtual std::vector<gr_complex> taps() const = 0;
- };
-
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H */
diff --git a/gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h b/gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h
deleted file mode 100644
index 81d11d6fd6..0000000000
--- a/gr-filter/include/gnuradio/filter/adaptive_fir_ccf.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H
-#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H
-
-#include <gnuradio/filter/api.h>
-#include <gnuradio/sync_decimator.h>
-
-namespace gr {
- namespace filter {
-
- /*!
- * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps
- * \ingroup filter_blk
- *
- * \details
- * This is a base class to implement an adaptive FIR
- * filter. Generally, another block will inherit from this one to
- * build a new type of adaptive filter such as an equalizer.
- *
- * This class implements two functions that are designed to be
- * overloaded by the child class: error(gr_complex out) and
- * update_tap(float tap, gr_complex in).
- *
- * The error() function calculates the error value that will be
- * used to adjust the taps. The update_tap function then uses the
- * error and the input signal value to update a particular
- * tap. Typically, the error is calculated for a given output and
- * then this is used in a loop to update all of the filter taps in
- * a loop:
- *
- * \code
- * d_error = error(sum);
- * for(k = 0; k < l; k++) {
- * update_tap(d_taps[ntaps-k-1], in[i+k]);
- * }
- * \endcode
- */
- class FILTER_API adaptive_fir_ccf : virtual public sync_decimator
- {
- public:
- // gr::filter::adaptive_fir_ccf::sptr
- typedef boost::shared_ptr<adaptive_fir_ccf> sptr;
-
- /*!
- * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps
- *
- * \param name Provides a name to identify this type of algorithm
- * \param decimation (interger) decimation rate of the filter
- * \param taps (real) filter taps
- */
- static sptr make(const char *name, int decimation,
- const std::vector<float> &taps);
-
- virtual void set_taps(const std::vector<float> &taps) = 0;
- virtual std::vector<float> taps() = 0;
- };
-
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H */
diff --git a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
index 822206889f..da4eb2bd34 100644
--- a/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
+++ b/gr-filter/include/gnuradio/filter/pfb_decimator_ccf.h
@@ -120,7 +120,7 @@ namespace gr {
*/
virtual void print_taps() = 0;
- //virtual void set_channel(unsigned int channel) = 0;
+ virtual void set_channel(const unsigned int channel) = 0;
};
} /* namespace filter */
diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt
index db9b0cfcb9..58000bbfcd 100644
--- a/gr-filter/lib/CMakeLists.txt
+++ b/gr-filter/lib/CMakeLists.txt
@@ -115,7 +115,6 @@ endif(ENABLE_GR_CTRLPORT)
# Setup library
########################################################################
list(APPEND filter_sources
- adaptive_fir.cc
fir_filter.cc
fir_filter_with_buffer.cc
fft_filter.cc
@@ -125,8 +124,6 @@ list(APPEND filter_sources
pm_remez.cc
polyphase_filterbank.cc
${generated_sources}
- adaptive_fir_ccc_impl.cc
- adaptive_fir_ccf_impl.cc
dc_blocker_cc_impl.cc
dc_blocker_ff_impl.cc
filter_delay_fc_impl.cc
diff --git a/gr-filter/lib/adaptive_fir.cc b/gr-filter/lib/adaptive_fir.cc
deleted file mode 100644
index a7ee8228a0..0000000000
--- a/gr-filter/lib/adaptive_fir.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <gnuradio/filter/adaptive_fir.h>
-#include <gnuradio/io_signature.h>
-
-namespace gr {
- namespace filter {
- namespace kernel {
-
- adaptive_fir_ccc::adaptive_fir_ccc(int decimation,
- const std::vector<gr_complex> &taps)
- : fir_filter_ccc(decimation, taps)
- {
- }
-
- adaptive_fir_ccc::~adaptive_fir_ccc()
- {
- }
-
-
- /**************************************************************/
-
-
- adaptive_fir_ccf::adaptive_fir_ccf(int decimation,
- const std::vector<float> &taps)
- : fir_filter_ccf(decimation, taps)
- {
- }
-
- adaptive_fir_ccf::~adaptive_fir_ccf()
- {
- }
-
- } /* namespace kernel */
- } /* namespace filter */
-} /* namespace gr */
diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.cc b/gr-filter/lib/adaptive_fir_ccc_impl.cc
deleted file mode 100644
index 93c7dea443..0000000000
--- a/gr-filter/lib/adaptive_fir_ccc_impl.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "adaptive_fir_ccc_impl.h"
-#include <gnuradio/io_signature.h>
-
-namespace gr {
- namespace filter {
-
- adaptive_fir_ccc::sptr adaptive_fir_ccc::make(const char *name, int decimation,
- const std::vector<gr_complex> &taps)
- {
- return gnuradio::get_initial_sptr(new adaptive_fir_ccc_impl
- (name, decimation, taps));
- }
-
- adaptive_fir_ccc_impl::adaptive_fir_ccc_impl(const char *name, int decimation,
- const std::vector<gr_complex> &taps)
- : sync_decimator(name,
- io_signature::make(1, 1, sizeof(gr_complex)),
- io_signature::make(1, 1, sizeof(gr_complex)),
- decimation),
- kernel::adaptive_fir_ccc(decimation, taps),
- d_updated(false)
- {
- set_history(d_ntaps);
- }
-
- void
- adaptive_fir_ccc_impl::set_taps(const std::vector<gr_complex> &taps)
- {
- d_new_taps = taps;
- d_updated = true;
- }
-
- std::vector<gr_complex>
- adaptive_fir_ccc_impl::taps() const
- {
- return kernel::fir_filter_ccc::taps();
- }
-
- gr_complex
- adaptive_fir_ccc_impl::error(const gr_complex &out)
- {
- return 0;
- }
-
- void
- adaptive_fir_ccc_impl::update_tap(gr_complex &tap, const gr_complex &in)
- {
- tap = tap;
- }
-
- int
- adaptive_fir_ccc_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- gr_complex *in = (gr_complex *)input_items[0];
- gr_complex *out = (gr_complex *)output_items[0];
-
- if (d_updated) {
- kernel::fir_filter_ccc::set_taps(d_new_taps);
- set_history(d_ntaps);
- d_updated = false;
- return 0; // history requirements may have changed.
- }
-
- // Call base class filtering function that uses
- // overloaded error and update_tap functions.
- if (decimation() == 1) {
- filterN(out, in, noutput_items);
- }
- else {
- filterNdec(out, in, noutput_items,
- decimation());
- }
-
- return noutput_items;
- }
-
- } /* namespace filter */
-} /* namespace gr */
diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.h b/gr-filter/lib/adaptive_fir_ccc_impl.h
deleted file mode 100644
index 66b8fe5a49..0000000000
--- a/gr-filter/lib/adaptive_fir_ccc_impl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H
-#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H
-
-#include <gnuradio/filter/adaptive_fir_ccc.h>
-#include <gnuradio/filter/adaptive_fir.h>
-#include <gnuradio/types.h>
-
-namespace gr {
- namespace filter {
-
- class FILTER_API adaptive_fir_ccc_impl :
- public adaptive_fir_ccc, public kernel::adaptive_fir_ccc
- {
- private:
- std::vector<gr_complex> d_new_taps;
- bool d_updated;
-
- protected:
- // Override to calculate error signal per output
- gr_complex error(const gr_complex &out);
-
- // Override to calculate new weight from old, corresponding input
- void update_tap(gr_complex &tap, const gr_complex &in);
-
- public:
- void set_taps(const std::vector<gr_complex> &taps);
- std::vector<gr_complex> taps() const;
-
- adaptive_fir_ccc_impl(const char *name, int decimation,
- const std::vector<gr_complex> &taps);
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H */
diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.cc b/gr-filter/lib/adaptive_fir_ccf_impl.cc
deleted file mode 100644
index 16d59f36f3..0000000000
--- a/gr-filter/lib/adaptive_fir_ccf_impl.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "adaptive_fir_ccf_impl.h"
-#include <gnuradio/io_signature.h>
-
-namespace gr {
- namespace filter {
-
- adaptive_fir_ccf::sptr adaptive_fir_ccf::make(const char *name, int decimation,
- const std::vector<float> &taps)
- {
- return gnuradio::get_initial_sptr(new adaptive_fir_ccf_impl
- (name, decimation, taps));
- }
-
- adaptive_fir_ccf_impl::adaptive_fir_ccf_impl(const char *name, int decimation,
- const std::vector<float> &taps)
- : sync_decimator(name,
- io_signature::make(1, 1, sizeof(gr_complex)),
- io_signature::make(1, 1, sizeof(gr_complex)),
- decimation),
- kernel::adaptive_fir_ccf(decimation, taps),
- d_updated(false)
- {
- set_history(d_ntaps);
- }
-
- void
- adaptive_fir_ccf_impl::set_taps(const std::vector<float> &taps)
- {
- d_new_taps = taps;
- d_updated = true;
- }
-
- std::vector<float>
- adaptive_fir_ccf_impl::taps()
- {
- return kernel::fir_filter_ccf::taps();
- }
-
- float
- adaptive_fir_ccf_impl::error(const gr_complex &out)
- {
- return 0;
- }
-
- void
- adaptive_fir_ccf_impl::update_tap(float &tap, const gr_complex &in)
- {
- tap = tap;
- }
-
- int
- adaptive_fir_ccf_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
- {
- gr_complex *in = (gr_complex *)input_items[0];
- gr_complex *out = (gr_complex *)output_items[0];
-
- if (d_updated) {
- kernel::fir_filter_ccf::set_taps(d_new_taps);
- set_history(d_ntaps);
- d_updated = false;
- return 0; // history requirements may have changed.
- }
-
- // Call base class filtering function that uses
- // overloaded error and update_tap functions.
- if (decimation() == 1) {
- filterN(out, in, noutput_items);
- }
- else {
- filterNdec(out, in, noutput_items,
- decimation());
- }
-
- return noutput_items;
- }
-
- } /* namespace filter */
-} /* namespace gr */
diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.h b/gr-filter/lib/adaptive_fir_ccf_impl.h
deleted file mode 100644
index 188587ee56..0000000000
--- a/gr-filter/lib/adaptive_fir_ccf_impl.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2011,2012 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * GNU Radio is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * GNU Radio is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Radio; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H
-#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H
-
-#include <gnuradio/filter/adaptive_fir_ccf.h>
-#include <gnuradio/filter/adaptive_fir.h>
-#include <gnuradio/types.h>
-
-namespace gr {
- namespace filter {
-
- class FILTER_API adaptive_fir_ccf_impl :
- public adaptive_fir_ccf, public kernel::adaptive_fir_ccf
- {
- private:
- std::vector<float> d_new_taps;
- bool d_updated;
-
- protected:
- // Override to calculate error signal per output
- float error(const gr_complex &out);
-
- // Override to calculate new weight from old, corresponding input
- void update_tap(float &tap, const gr_complex &in);
-
- public:
- void set_taps(const std::vector<float> &taps);
- std::vector<float> taps();
-
- adaptive_fir_ccf_impl(const char *name, int decimation,
- const std::vector<float> &taps);
-
- int work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items);
- };
-
- } /* namespace filter */
-} /* namespace gr */
-
-#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H */
diff --git a/gr-filter/lib/firdes.cc b/gr-filter/lib/firdes.cc
index a52a2ddf63..cb6bffd18a 100644
--- a/gr-filter/lib/firdes.cc
+++ b/gr-filter/lib/firdes.cc
@@ -658,21 +658,6 @@ namespace gr {
// === Utilities ===
//
- // delta_f / width_factor gives number of taps required.
- const int MAX_WIDTH_FACTOR = 8;
- static const float width_factor[8] = { // indexed by win_type
- 3.3, // WIN_HAMMING
- 3.1, // WIN_HANN
- 5.5, // WIN_BLACKMAN
- 2.0, // WIN_RECTANGULAR
- //5.0 // WIN_KAISER (guesstimate compromise)
- //2.0 // WIN_KAISER (guesstimate compromise)
- 10.0, // WIN_KAISER
- 6.0, // WIN_BLACKMAN_HARRIS (est.)
- 3.0, // WIN_BARTLETT (est.)
- 5.5, // WIN_FLATTOP (est.)
- };
-
int
firdes::compute_ntaps_windes(double sampling_freq,
double transition_width, // this is frequency, not relative frequency
@@ -692,14 +677,8 @@ namespace gr {
win_type window_type,
double beta)
{
- // normalized transition width
- double delta_f = transition_width / sampling_freq;
-
- // compute number of taps required for given transition width
- if(window_type >= MAX_WIDTH_FACTOR)
- throw std::runtime_error("firdes::compute_ntaps: window_type out of range.");
-
- int ntaps = (int)(width_factor[window_type] / delta_f + 0.5);
+ double a = fft::window::max_attenuation(static_cast<fft::window::win_type>(window_type), beta);
+ int ntaps = (int)(a*sampling_freq/(22.0*transition_width));
if((ntaps & 1) == 0) // if even...
ntaps++; // ...make odd
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc
index b025060dc3..19cf20f410 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.cc
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc
@@ -83,6 +83,13 @@ namespace gr {
return polyphase_filterbank::taps();
}
+ void
+ pfb_decimator_ccf_impl::set_channel(const unsigned int chan)
+ {
+ gr::thread::scoped_lock guard(d_mutex);
+ d_chan = chan;
+ }
+
#define ROTATEFFT
int
diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.h b/gr-filter/lib/pfb_decimator_ccf_impl.h
index eeebc2c3a7..2df8a506f0 100644
--- a/gr-filter/lib/pfb_decimator_ccf_impl.h
+++ b/gr-filter/lib/pfb_decimator_ccf_impl.h
@@ -52,7 +52,7 @@ namespace gr {
void set_taps(const std::vector<float> &taps);
void print_taps();
std::vector<std::vector<float> > taps() const;
- //void set_channel(unsigned int channel);
+ void set_channel(const unsigned int channel);
int work(int noutput_items,
gr_vector_const_void_star &input_items,
diff --git a/gr-filter/lib/qa_firdes.cc b/gr-filter/lib/qa_firdes.cc
index dfc5e00f35..b17337001e 100644
--- a/gr-filter/lib/qa_firdes.cc
+++ b/gr-filter/lib/qa_firdes.cc
@@ -31,456 +31,120 @@
namespace gr {
namespace filter {
-
+
#define NELEM(x) (sizeof(x) / sizeof(x[0]))
using std::vector;
-
-#if 0
- static void
+
+ void
print_taps(std::ostream &s, vector<float> &v)
{
-
+ std::streamsize tmp = s.precision(9);
for(unsigned int i = 0; i < v.size(); i++) {
- printf("tap[%2d] = %16.7e\n", i, v[i]);
+ s << v[i] << ", ";
}
+ s << std::endl;
+ s.precision(tmp);
}
-#endif
-
+
static void
check_symmetry(vector<float> &v)
{
int n = v.size();
int m = n / 2;
-
+
for(int i = 0; i < m; i++)
CPPUNIT_ASSERT_DOUBLES_EQUAL(v[i], v[n - i - 1], 1e-9);
}
- const static float t1_exp[53] = {
- -9.0525491e-04,
- 2.0713841e-04,
- 1.2388536e-03,
- 2.9683491e-04,
- -1.7744775e-03,
- -1.3599906e-03,
- 2.2031884e-03,
- 3.2744040e-03,
- -1.8868084e-03,
- -5.9935520e-03,
- 6.4301129e-18,
- 8.9516686e-03,
- 4.2178580e-03,
- -1.0998557e-02,
- -1.1173409e-02,
- 1.0455756e-02,
- 2.0686293e-02,
- -5.2032238e-03,
- -3.1896964e-02,
- -7.4998410e-03,
- 4.3362070e-02,
- 3.2502845e-02,
- -5.3328082e-02,
- -8.5621715e-02,
- 6.0117975e-02,
- 3.1128189e-01,
- 4.3769023e-01,
- 3.1128189e-01,
- 6.0117975e-02,
- -8.5621715e-02,
- -5.3328082e-02,
- 3.2502845e-02,
- 4.3362070e-02,
- -7.4998410e-03,
- -3.1896964e-02,
- -5.2032238e-03,
- 2.0686293e-02,
- 1.0455756e-02,
- -1.1173409e-02,
- -1.0998557e-02,
- 4.2178580e-03,
- 8.9516686e-03,
- 6.4301129e-18,
- -5.9935520e-03,
- -1.8868084e-03,
- 3.2744040e-03,
- 2.2031884e-03,
- -1.3599906e-03,
- -1.7744775e-03,
- 2.9683491e-04,
- 1.2388536e-03,
- 2.0713841e-04,
- -9.0525491e-04
+ const static float t1_exp[39] = {
+ 0.00111410965, -0.000583702058, -0.00192639488, 2.30933896e-18, 0.00368289859,
+ 0.00198723329, -0.0058701504, -0.00666110823, 0.0068643163, 0.0147596458,
+ -0.00398709066, -0.0259727165, -0.0064281947, 0.0387893915, 0.0301109217,
+ -0.0507995859, -0.0833103433, 0.0593735874, 0.310160041, 0.437394291,
+ 0.310160041, 0.0593735874, -0.0833103433, -0.0507995859, 0.0301109217,
+ 0.0387893915, -0.0064281947, -0.0259727165, -0.00398709066, 0.0147596458,
+ 0.0068643163, -0.00666110823, -0.0058701504, 0.00198723329, 0.00368289859,
+ 2.30933896e-18, -0.00192639488, -0.000583702058, 0.00111410965
};
- const static float t2_exp[53] = {
- 9.0380036e-04,
- -2.0680559e-04,
- -1.2368630e-03,
- -2.9635796e-04,
- 1.7716263e-03,
- 1.3578053e-03,
- -2.1996482e-03,
- -3.2691427e-03,
- 1.8837767e-03,
- 5.9839217e-03,
- -6.4197810e-18,
- -8.9372853e-03,
- -4.2110807e-03,
- 1.0980885e-02,
- 1.1155456e-02,
- -1.0438956e-02,
- -2.0653054e-02,
- 5.1948633e-03,
- 3.1845711e-02,
- 7.4877902e-03,
- -4.3292396e-02,
- -3.2450620e-02,
- 5.3242393e-02,
- 8.5484132e-02,
- -6.0021374e-02,
- -3.1078172e-01,
- 5.6184036e-01,
- -3.1078172e-01,
- -6.0021374e-02,
- 8.5484132e-02,
- 5.3242393e-02,
- -3.2450620e-02,
- -4.3292396e-02,
- 7.4877902e-03,
- 3.1845711e-02,
- 5.1948633e-03,
- -2.0653054e-02,
- -1.0438956e-02,
- 1.1155456e-02,
- 1.0980885e-02,
- -4.2110807e-03,
- -8.9372853e-03,
- -6.4197810e-18,
- 5.9839217e-03,
- 1.8837767e-03,
- -3.2691427e-03,
- -2.1996482e-03,
- 1.3578053e-03,
- 1.7716263e-03,
- -2.9635796e-04,
- -1.2368630e-03,
- -2.0680559e-04,
- 9.0380036e-04
+ const static float t2_exp[39] = {
+ -0.00111255341, 0.000582886743, 0.00192370394, -2.30611317e-18, -0.0036777542,
+ -0.00198445749, 0.00586195057, 0.00665180339, -0.00685472786, -0.0147390282,
+ 0.00398152089, 0.0259364359, 0.00641921535, -0.0387352072, -0.0300688613,
+ 0.0507286265, 0.0831939653, -0.0592906512, -0.309726775, 0.561578512,
+ -0.309726775, -0.0592906512, 0.0831939653, 0.0507286265, -0.0300688613,
+ -0.0387352072, 0.00641921535, 0.0259364359, 0.00398152089, -0.0147390282,
+ -0.00685472786, 0.00665180339, 0.00586195057, -0.00198445749, -0.0036777542,
+ -2.30611317e-18, 0.00192370394, 0.000582886743, -0.00111255341
};
-
- const static float t3_exp[107] = {
- -1.8970841e-06,
- -7.1057165e-04,
- 5.4005696e-04,
- 4.6233178e-04,
- 2.0572044e-04,
- 3.5209916e-04,
- -1.4098573e-03,
- 1.1279077e-04,
- -6.2994129e-04,
- 1.1450432e-03,
- 1.3637283e-03,
- -6.4360141e-04,
- 3.6509900e-04,
- -3.2864159e-03,
- 7.0192874e-04,
- 3.7524730e-04,
- 2.0256115e-03,
- 3.0641893e-03,
- -3.6618244e-03,
- 7.5592739e-05,
- -5.5586505e-03,
- 2.3849572e-03,
- 4.0114378e-03,
- 1.6636450e-03,
- 4.7835698e-03,
- -1.0191196e-02,
- -3.8158931e-04,
- -5.5551580e-03,
- 5.3901658e-03,
- 1.1366769e-02,
- -3.0000482e-03,
- 4.9341680e-03,
- -2.0093076e-02,
- 5.5752542e-17,
- 1.2093617e-03,
- 8.6089745e-03,
- 2.2382140e-02,
- -1.6854567e-02,
- 1.6913920e-03,
- -3.1222520e-02,
- 3.2711059e-03,
- 2.2604836e-02,
- 8.1451107e-03,
- 3.7583180e-02,
- -5.2293688e-02,
- -8.0551542e-03,
- -4.0092729e-02,
- 1.5582236e-02,
- 9.7452506e-02,
- -1.6183170e-02,
- 8.3281815e-02,
- -2.8196752e-01,
- -1.0965768e-01,
- 5.2867508e-01,
- -1.0965768e-01,
- -2.8196752e-01,
- 8.3281815e-02,
- -1.6183170e-02,
- 9.7452506e-02,
- 1.5582236e-02,
- -4.0092729e-02,
- -8.0551542e-03,
- -5.2293688e-02,
- 3.7583180e-02,
- 8.1451107e-03,
- 2.2604836e-02,
- 3.2711059e-03,
- -3.1222520e-02,
- 1.6913920e-03,
- -1.6854567e-02,
- 2.2382140e-02,
- 8.6089745e-03,
- 1.2093617e-03,
- 5.5752542e-17,
- -2.0093076e-02,
- 4.9341680e-03,
- -3.0000482e-03,
- 1.1366769e-02,
- 5.3901658e-03,
- -5.5551580e-03,
- -3.8158931e-04,
- -1.0191196e-02,
- 4.7835698e-03,
- 1.6636450e-03,
- 4.0114378e-03,
- 2.3849572e-03,
- -5.5586505e-03,
- 7.5592739e-05,
- -3.6618244e-03,
- 3.0641893e-03,
- 2.0256115e-03,
- 3.7524730e-04,
- 7.0192874e-04,
- -3.2864159e-03,
- 3.6509900e-04,
- -6.4360141e-04,
- 1.3637283e-03,
- 1.1450432e-03,
- -6.2994129e-04,
- 1.1279077e-04,
- -1.4098573e-03,
- 3.5209916e-04,
- 2.0572044e-04,
- 4.6233178e-04,
- 5.4005696e-04,
- -7.1057165e-04,
- -1.8970841e-06
+
+ const static float t3_exp[77] = {
+ 0.000119983582, 0.000607753696, 0.000897691818, -0.0010834164, 2.31763315e-05,
+ -0.00179765455, 0.000822491478, 0.0014836716, 0.000661226455, 0.00204213755,
+ -0.00466352375, -0.000186616904, -0.00289339852, 0.00297895772, 0.00664081471,
+ -0.00184599939, 0.00318629085, -0.0135707017, 3.90737225e-17, 0.000884963025,
+ 0.00652826019, 0.0175401419, -0.013614703, 0.00140484457, -0.0266032815,
+ 0.00285289111, 0.0201372877, 0.00739659835, 0.0347237773, -0.0490655154,
+ -0.00766157778, -0.0385900773, 0.0151521852, 0.0955788717, -0.0159830209,
+ 0.0826964602, -0.281061709, -0.109556615, 0.528591633, -0.109556615,
+ -0.281061709, 0.0826964602, -0.0159830209, 0.0955788717, 0.0151521852,
+ -0.0385900773, -0.00766157778, -0.0490655154, 0.0347237773, 0.00739659835,
+ 0.0201372877, 0.00285289111, -0.0266032815, 0.00140484457, -0.013614703,
+ 0.0175401419, 0.00652826019, 0.000884963025, 3.90737225e-17, -0.0135707017,
+ 0.00318629085, -0.00184599939, 0.00664081471, 0.00297895772, -0.00289339852,
+ -0.000186616904, -0.00466352375, 0.00204213755, 0.000661226455, 0.0014836716,
+ 0.000822491478, -0.00179765455, 2.31763315e-05, -0.0010834164, 0.000897691818,
+ 0.000607753696, 0.000119983582
};
-
- const static float t4_exp[] = { // low pass
- 0.001059958362,
- 0.0002263929928,
- -0.001277606934,
- -0.0009675776237,
- 0.001592264394,
- 0.00243603508,
- -0.001451682881,
- -0.004769335967,
- 5.281541594e-18,
- 0.007567512803,
- 0.003658855334,
- -0.009761494584,
- -0.01011830103,
- 0.009636915289,
- 0.0193619132,
- -0.004935568199,
- -0.03060629964,
- -0.007267376408,
- 0.04236677289,
- 0.03197422624,
- -0.05274848267,
- -0.0850463286,
- 0.05989059806,
- 0.31065014,
- 0.4370569289,
- 0.31065014,
- 0.05989059806,
- -0.0850463286,
- -0.05274848267,
- 0.03197422624,
- 0.04236677289,
- -0.007267376408,
- -0.03060629964,
- -0.004935568199,
- 0.0193619132,
- 0.009636915289,
- -0.01011830103,
- -0.009761494584,
- 0.003658855334,
- 0.007567512803,
- 5.281541594e-18,
- -0.004769335967,
- -0.001451682881,
- 0.00243603508,
- 0.001592264394,
- -0.0009675776237,
- -0.001277606934,
- 0.0002263929928,
- 0.001059958362,
+
+ const static float t4_exp[49] = { // low pass
+ 0.00105995836, 0.000226392993, -0.00127760693, -0.000967577624, 0.00159226439,
+ 0.00243603508, -0.00145168288, -0.00476933597, 5.28154159e-18, 0.0075675128,
+ 0.00365885533, -0.00976149458, -0.010118301, 0.00963691529, 0.0193619132,
+ -0.0049355682, -0.0306062996, -0.00726737641, 0.0423667729, 0.0319742262,
+ -0.0527484827, -0.0850463286, 0.0598905981, 0.31065014, 0.437056929,
+ 0.31065014, 0.0598905981, -0.0850463286, -0.0527484827, 0.0319742262,
+ 0.0423667729, -0.00726737641, -0.0306062996, -0.0049355682, 0.0193619132,
+ 0.00963691529, -0.010118301, -0.00976149458, 0.00365885533, 0.0075675128,
+ 5.28154159e-18, -0.00476933597, -0.00145168288, 0.00243603508, 0.00159226439,
+ -0.000967577624, -0.00127760693, 0.000226392993, 0.00105995836
};
- const static float t5_exp[] = { //high pass
- -0.001062123571,
- -0.0002268554381,
- 0.001280216733,
- 0.000969554123,
- -0.001595516922,
- -0.002441011136,
- 0.001454648213,
- 0.004779078532,
- -5.292330097e-18,
- -0.007582970895,
- -0.00366632943,
- 0.009781434201,
- 0.01013896987,
- -0.009656600654,
- -0.01940146461,
- 0.004945650231,
- 0.03066881932,
- 0.00728222169,
- -0.04245331511,
- -0.03203954175,
- 0.05285623297,
- 0.08522006124,
- -0.06001294032,
- -0.3112847209,
- 0.5630782247,
- -0.3112847209,
- -0.06001294032,
- 0.08522006124,
- 0.05285623297,
- -0.03203954175,
- -0.04245331511,
- 0.00728222169,
- 0.03066881932,
- 0.004945650231,
- -0.01940146461,
- -0.009656600654,
- 0.01013896987,
- 0.009781434201,
- -0.00366632943,
- -0.007582970895,
- -5.292330097e-18,
- 0.004779078532,
- 0.001454648213,
- -0.002441011136,
- -0.001595516922,
- 0.000969554123,
- 0.001280216733,
- -0.0002268554381,
- -0.001062123571,
+ const static float t5_exp[49] = { //high pass
+ -0.00106212357, -0.000226855438, 0.00128021673, 0.000969554123, -0.00159551692,
+ -0.00244101114, 0.00145464821, 0.00477907853, -5.2923301e-18, -0.00758297089,
+ -0.00366632943, 0.0097814342, 0.0101389699, -0.00965660065, -0.0194014646,
+ 0.00494565023, 0.0306688193, 0.00728222169, -0.0424533151, -0.0320395418,
+ 0.052856233, 0.0852200612, -0.0600129403, -0.311284721, 0.563078225,
+ -0.311284721, -0.0600129403, 0.0852200612, 0.052856233, -0.0320395418,
+ -0.0424533151, 0.00728222169, 0.0306688193, 0.00494565023, -0.0194014646,
+ -0.00965660065, 0.0101389699, 0.0097814342, -0.00366632943, -0.00758297089,
+ -5.2923301e-18, 0.00477907853, 0.00145464821, -0.00244101114, -0.00159551692,
+ 0.000969554123, 0.00128021673, -0.000226855438, -0.00106212357
};
-
+
const static float t6_exp[] = { // bandpass
- 0.0002809273137,
- -0.001047327649,
- 7.936541806e-05,
- -0.0004270860809,
- 0.0007595835486,
- 0.0008966081077,
- -0.0004236323002,
- 0.0002423936094,
- -0.002212299034,
- 0.0004807534278,
- 0.0002620361629,
- 0.001443728455,
- 0.002229931997,
- -0.002720607212,
- 5.731141573e-05,
- -0.004297634587,
- 0.001878833398,
- 0.003217151389,
- 0.001357055153,
- 0.003965090029,
- -0.008576190099,
- -0.0003257228818,
- -0.004805727862,
- 0.004721920472,
- 0.01007549558,
- -0.002688719891,
- 0.004467967432,
- -0.01837076992,
- 5.119658377e-17,
- 0.001125075156,
- 0.008071650751,
- 0.02113764361,
- -0.01602453552,
- 0.001618095324,
- -0.03004053794,
- 0.003163811285,
- 0.0219683405,
- 0.007950295694,
- 0.03682873398,
- -0.05142467469,
- -0.00794606097,
- -0.03965795785,
- 0.01544955093,
- 0.09681399167,
- -0.01610304788,
- 0.08297294378,
- -0.2811714709,
- -0.1094062924,
- 0.5275565982,
- -0.1094062924,
- -0.2811714709,
- 0.08297294378,
- -0.01610304788,
- 0.09681399167,
- 0.01544955093,
- -0.03965795785,
- -0.00794606097,
- -0.05142467469,
- 0.03682873398,
- 0.007950295694,
- 0.0219683405,
- 0.003163811285,
- -0.03004053794,
- 0.001618095324,
- -0.01602453552,
- 0.02113764361,
- 0.008071650751,
- 0.001125075156,
- 5.119658377e-17,
- -0.01837076992,
- 0.004467967432,
- -0.002688719891,
- 0.01007549558,
- 0.004721920472,
- -0.004805727862,
- -0.0003257228818,
- -0.008576190099,
- 0.003965090029,
- 0.001357055153,
- 0.003217151389,
- 0.001878833398,
- -0.004297634587,
- 5.731141573e-05,
- -0.002720607212,
- 0.002229931997,
- 0.001443728455,
- 0.0002620361629,
- 0.0004807534278,
- -0.002212299034,
- 0.0002423936094,
- -0.0004236323002,
- 0.0008966081077,
- 0.0007595835486,
- -0.0004270860809,
- 7.936541806e-05,
- -0.001047327649,
- 0.0002809273137,
+ 0.000280927314, -0.00104732765, 7.93654181e-05, -0.000427086081, 0.000759583549,
+ 0.000896608108, -0.0004236323, 0.000242393609, -0.00221229903, 0.000480753428,
+ 0.000262036163, 0.00144372846, 0.002229932, -0.00272060721, 5.73114157e-05,
+ -0.00429763459, 0.0018788334, 0.00321715139, 0.00135705515, 0.00396509003,
+ -0.0085761901, -0.000325722882, -0.00480572786, 0.00472192047, 0.0100754956,
+ -0.00268871989, 0.00446796743, -0.0183707699, 5.11965838e-17, 0.00112507516,
+ 0.00807165075, 0.0211376436, -0.0160245355, 0.00161809532, -0.0300405379,
+ 0.00316381129, 0.0219683405, 0.00795029569, 0.036828734, -0.0514246747,
+ -0.00794606097, -0.0396579579, 0.0154495509, 0.0968139917, -0.0161030479,
+ 0.0829729438, -0.281171471, -0.109406292, 0.527556598, -0.109406292,
+ -0.281171471, 0.0829729438, -0.0161030479, 0.0968139917, 0.0154495509,
+ -0.0396579579, -0.00794606097, -0.0514246747, 0.036828734, 0.00795029569,
+ 0.0219683405, 0.00316381129, -0.0300405379, 0.00161809532, -0.0160245355,
+ 0.0211376436, 0.00807165075, 0.00112507516, 5.11965838e-17, -0.0183707699,
+ 0.00446796743, -0.00268871989, 0.0100754956, 0.00472192047, -0.00480572786,
+ -0.000325722882, -0.0085761901, 0.00396509003, 0.00135705515, 0.00321715139,
+ 0.0018788334, -0.00429763459, 5.73114157e-05, -0.00272060721, 0.002229932,
+ 0.00144372846, 0.000262036163, 0.000480753428, -0.00221229903, 0.000242393609,
+ -0.0004236323, 0.000896608108, 0.000759583549, -0.000427086081, 7.93654181e-05,
+ -0.00104732765, 0.000280927314
};
void
@@ -492,17 +156,17 @@ namespace gr {
1750,
500,
firdes::WIN_HAMMING);
-
- // cout << "ntaps: " << taps.size() << endl;
- // print_taps(cout, taps);
+
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
CPPUNIT_ASSERT_EQUAL(NELEM(t1_exp), taps.size());
for(unsigned int i = 0; i < taps.size(); i++)
CPPUNIT_ASSERT_DOUBLES_EQUAL(t1_exp[i], taps[i], 1e-9);
check_symmetry(taps);
-}
-
+ }
+
void
qa_firdes::t2()
{
@@ -513,14 +177,14 @@ namespace gr {
500,
firdes::WIN_HAMMING);
- // cout << "ntaps: " << taps.size() << endl;
- // print_taps(cout, taps);
-
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
+
CPPUNIT_ASSERT_EQUAL(NELEM(t2_exp), taps.size());
for(unsigned int i = 0; i < taps.size(); i++)
CPPUNIT_ASSERT_DOUBLES_EQUAL(t2_exp[i], taps[i], 1e-9);
-
+
check_symmetry(taps);
}
@@ -535,8 +199,8 @@ namespace gr {
0.62e6,
firdes::WIN_HAMMING);
- // cout << "ntaps: " << taps.size() << endl;
- // print_taps(cout, taps);
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
CPPUNIT_ASSERT_EQUAL(NELEM(t3_exp), taps.size());
@@ -557,8 +221,8 @@ namespace gr {
66,
firdes::WIN_HAMMING);
- // std::cout << "ntaps: " << taps.size() << std::endl;
- // print_taps(std::cout, taps);
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
CPPUNIT_ASSERT_EQUAL(NELEM(t4_exp), taps.size());
for(unsigned int i = 0; i < taps.size(); i++)
@@ -578,14 +242,14 @@ namespace gr {
66,
firdes::WIN_HAMMING);
- // std::cout << "ntaps: " << taps.size() << std::endl;
- // print_taps(std::cout, taps);
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
CPPUNIT_ASSERT_EQUAL(NELEM(t5_exp), taps.size());
for(unsigned int i = 0; i < taps.size(); i++)
CPPUNIT_ASSERT_DOUBLES_EQUAL(t5_exp[i], taps[i], 1e-9);
-
+
check_symmetry(taps);
}
@@ -601,8 +265,8 @@ namespace gr {
66,
firdes::WIN_HAMMING);
- // std::cout << "ntaps: " << taps.size() << std::endl;
- // print_taps(std::cout, taps);
+ // std::cout << "ntaps: " << taps.size() << std::endl;
+ // print_taps(std::cout, taps);
CPPUNIT_ASSERT_EQUAL(NELEM(t6_exp), taps.size());
diff --git a/gr-filter/python/filter/CMakeLists.txt b/gr-filter/python/filter/CMakeLists.txt
index bf91f87447..e83e6dd3ad 100644
--- a/gr-filter/python/filter/CMakeLists.txt
+++ b/gr-filter/python/filter/CMakeLists.txt
@@ -46,6 +46,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-filter/python/filter/pfb.py b/gr-filter/python/filter/pfb.py
index 52f598cc40..2ddf65962c 100644
--- a/gr-filter/python/filter/pfb.py
+++ b/gr-filter/python/filter/pfb.py
@@ -169,6 +169,12 @@ class decimator_ccf(gr.hier_block2):
self.connect(self.pfb, self)
+ def set_taps(self, taps):
+ self.pfb.set_taps(taps)
+
+ def set_channel(self, chan):
+ self.pfb.set_channel(chan)
+
class arb_resampler_ccf(gr.hier_block2):
'''
diff --git a/gr-filter/python/filter/qa_adaptive_fir_filter.py b/gr-filter/python/filter/qa_adaptive_fir_filter.py
deleted file mode 100755
index cb82c7e969..0000000000
--- a/gr-filter/python/filter/qa_adaptive_fir_filter.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2008,2010,2012,2013 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# GNU Radio is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-#
-# GNU Radio is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-
-from gnuradio import gr, gr_unittest, filter, blocks
-
-def fir_filter(x, taps, decim=1):
- y = []
- x2 = (len(taps)-1)*[0,] + x
- for i in range(0, len(x), decim):
- yi = 0
- for j in range(len(taps)):
- yi += taps[len(taps)-1-j] * x2[i+j]
- y.append(yi)
- return y
-
-class test_adaptive_filter(gr_unittest.TestCase):
-
- def setUp(self):
- self.tb = gr.top_block ()
-
- def tearDown(self):
- self.tb = None
-
- def test_adaptive_fir_filter_ccf_001(self):
- decim = 1
- taps = 20*[0.5, 0.5]
- src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
- expected_data = fir_filter(src_data, taps, decim)
-
- src = blocks.vector_source_c(src_data)
- op = filter.adaptive_fir_ccf("test", decim, taps)
- dst = blocks.vector_sink_c()
- self.tb.connect(src, op, dst)
- self.tb.run()
- result_data = dst.data()
- self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
-
- def test_adaptive_fir_filter_ccf_002(self):
- decim = 4
- taps = 20*[0.5, 0.5]
- src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
- expected_data = fir_filter(src_data, taps, decim)
-
- src = blocks.vector_source_c(src_data)
- op = filter.adaptive_fir_ccf("test", decim, taps)
- dst = blocks.vector_sink_c()
- self.tb.connect(src, op, dst)
- self.tb.run()
- result_data = dst.data()
- self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
-
- def test_adaptive_fir_filter_ccc_001(self):
- decim = 1
- taps = 20*[0.5+1j, 0.5+1j]
- src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
- expected_data = fir_filter(src_data, taps, decim)
-
- src = blocks.vector_source_c(src_data)
- op = filter.adaptive_fir_ccc("test", decim, taps)
- dst = blocks.vector_sink_c()
- self.tb.connect(src, op, dst)
- self.tb.run()
- result_data = dst.data()
- self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
-
-
- def test_adaptive_fir_filter_ccc_002(self):
- decim = 4
- taps = 20*[0.5+1j, 0.5+1j]
- src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j]
- expected_data = fir_filter(src_data, taps, decim)
-
- src = blocks.vector_source_c(src_data)
- op = filter.adaptive_fir_ccc("test", decim, taps)
- dst = blocks.vector_sink_c()
- self.tb.connect(src, op, dst)
- self.tb.run()
- result_data = dst.data()
- self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5)
-
-if __name__ == '__main__':
- gr_unittest.run(test_adaptive_filter, "test_adaptive_filter.xml")
-
diff --git a/gr-filter/python/filter/qa_firdes.py b/gr-filter/python/filter/qa_firdes.py
index d38af31822..b32e5b2f91 100755
--- a/gr-filter/python/filter/qa_firdes.py
+++ b/gr-filter/python/filter/qa_firdes.py
@@ -32,15 +32,14 @@ class test_firdes(gr_unittest.TestCase):
pass
def test_low_pass(self):
- known_taps = (0.0030193300917744637, -0.004960992839187384,
- 0.006678304169327021, -1.132049690556083e-17,
- -0.0251916591078043, 0.07206480950117111,
- -0.13062666356563568, 0.18007083237171173,
- 0.7978920936584473, 0.18007083237171173,
- -0.13062666356563568, 0.07206480950117111,
- -0.0251916591078043, -1.132049690556083e-17,
- 0.006678304169327021, -0.004960992839187384,
- 0.0030193300917744637)
+ known_taps = (0.0024871660862118006, -4.403502608370943e-18,
+ -0.014456653036177158, 0.0543283149600029,
+ -0.116202212870121, 0.17504146695137024,
+ 0.7976038455963135, 0.17504146695137024,
+ -0.116202212870121, 0.0543283149600029,
+ -0.014456653036177158, -4.403502608370943e-18,
+ 0.0024871660862118006)
+
new_taps = filter.firdes.low_pass(1, 1, 0.4, 0.2)
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
@@ -56,15 +55,13 @@ class test_firdes(gr_unittest.TestCase):
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
def test_high_pass(self):
- known_taps = (-0.003062003292143345, 0.005031108390539885,
- -0.0067726909182965755, 1.1480492661182674e-17,
- 0.025547700002789497, -0.0730833187699318,
- 0.13247284293174744, -0.18261581659317017,
- 0.20229223370552063, -0.18261581659317017,
- 0.13247284293174744, -0.0730833187699318,
- 0.025547700002789497, 1.1480492661182674e-17,
- -0.0067726909182965755, 0.005031108390539885,
- -0.003062003292143345)
+ known_taps = (-0.0027197482995688915, 4.815287179370254e-18,
+ 0.01580853760242462, -0.05940871313214302,
+ 0.1270686239004135, -0.1914101094007492,
+ 0.21804752945899963, -0.1914101094007492,
+ 0.1270686239004135, -0.05940871313214302,
+ 0.01580853760242462, 4.815287179370254e-18,
+ -0.0027197482995688915)
new_taps = filter.firdes.high_pass(1, 1, 0.4, 0.2)
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
@@ -80,15 +77,13 @@ class test_firdes(gr_unittest.TestCase):
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
def test_band_pass(self):
- known_taps = (0.004961997736245394, -0.008152946829795837,
- -0.004192151129245758, -5.749020235348687e-18,
- 0.01581347920000553, 0.11843203753232956,
- -0.21467317640781403, -0.11303528398275375,
- 0.40520283579826355, -0.11303528398275375,
- -0.21467317640781403, 0.11843203753232956,
- 0.01581347920000553, -5.749020235348687e-18,
- -0.004192151129245758, -0.008152946829795837,
- 0.004961997736245394)
+ known_taps = (-0.001676854444667697, -2.4018533253972557e-18,
+ 0.009746716357767582, 0.09589414298534393,
+ -0.20510689914226532, -0.11801345646381378,
+ 0.4350462853908539, -0.11801345646381378,
+ -0.20510689914226532, 0.09589414298534393,
+ 0.009746716357767582, -2.4018533253972557e-18,
+ -0.001676854444667697)
new_taps = filter.firdes.band_pass(1, 1, 0.2, 0.4, 0.2)
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
@@ -104,23 +99,19 @@ class test_firdes(gr_unittest.TestCase):
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
def test_complex_band_pass(self):
- known_taps = ((0.0024772135075181723+0.0017997993854805827j),
- (-0.004070250317454338+0.002957213670015335j),
- (-0.0020928815938532352-0.006441210396587849j),
- (-2.8701231652956686e-18+2.805614574993832e-24j),
- (0.007894645445048809-0.024297315627336502j),
- (0.05912570655345917+0.04295721650123596j),
- (-0.10717268288135529+0.07786571979522705j),
- (-0.0564316064119339-0.17367789149284363j),
- (0.20229223370552063-2.4115112751132983e-07j),
- (-0.05643119290471077+0.17367802560329437j),
- (-0.10717286914587021-0.07786546647548676j),
- (0.05912560224533081-0.0429573580622673j),
- (0.007894691079854965+0.024297300726175308j),
- (-2.8701231652956686e-18+2.6687109203363464e-24j),
- (-0.0020928694866597652+0.006441214121878147j),
- (-0.004070255905389786-0.0029572059866040945j),
- (0.0024772100150585175-0.0017998040420934558j))
+ known_taps = ((-0.0008404505206272006-0.0025866336654871702j),
+ (-1.2038217948425635e-18+1.1767648157397848e-24j),
+ (0.0048850891180336475-0.015034818090498447j),
+ (0.048062704503536224+0.03491950035095215j),
+ (-0.10280057787895203+0.07468919456005096j),
+ (-0.05914920195937157-0.18204176425933838j),
+ (0.21804752945899963-2.5993290364567656e-07j),
+ (-0.059148769825696945+0.18204189836978912j),
+ (-0.10280075669288635-0.07468894869089127j),
+ (0.04806262254714966-0.0349196158349514j),
+ (0.004885117989033461+0.015034808777272701j),
+ (-1.2038217948425635e-18+1.1193430388030685e-24j),
+ (-0.000840445572976023+0.002586635295301676j))
new_taps = filter.firdes.complex_band_pass(1, 1, 0.2, 0.4, 0.2)
self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5)
@@ -142,15 +133,13 @@ class test_firdes(gr_unittest.TestCase):
self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5)
def test_band_reject(self):
- known_taps = (-0.004915320314466953, 0.008076251484453678,
- 0.00415271520614624, 5.694938753309664e-18,
- -0.01566472090780735, -0.11731793731451035,
- 0.2126537412405014, 0.11197195947170258,
- 0.6020866632461548, 0.11197195947170258,
- 0.2126537412405014, -0.11731793731451035,
- -0.01566472090780735, 5.694938753309664e-18,
- 0.00415271520614624, 0.008076251484453678,
- -0.004915320314466953)
+ known_taps = (0.0015371545450761914, 2.201753372137003e-18,
+ -0.00893471110612154, -0.08790513873100281,
+ 0.1880193054676056, 0.1081816703081131,
+ 0.5982034206390381, 0.1081816703081131,
+ 0.1880193054676056, -0.08790513873100281,
+ -0.00893471110612154, 2.201753372137003e-18,
+ 0.0015371545450761914)
new_taps = filter.firdes.band_reject(1, 1, 0.2, 0.4, 0.2)
self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5)
diff --git a/gr-filter/python/filter/qa_freq_xlating_fir_filter.py b/gr-filter/python/filter/qa_freq_xlating_fir_filter.py
index 39a803715e..ca5245db64 100755
--- a/gr-filter/python/filter/qa_freq_xlating_fir_filter.py
+++ b/gr-filter/python/filter/qa_freq_xlating_fir_filter.py
@@ -91,7 +91,7 @@ class test_freq_xlating_filter(gr_unittest.TestCase):
def generate_scf_source(self):
self.fs = fs = 1
self.fc = fc = 0.3
- self.bw = bw = 0.1
+ self.bw = bw = 0.12
self.taps = filter.firdes.low_pass(1, fs, bw, bw/4)
times = xrange(100)
self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times)
@@ -99,7 +99,7 @@ class test_freq_xlating_filter(gr_unittest.TestCase):
def generate_scc_source(self):
self.fs = fs = 1
self.fc = fc = 0.3
- self.bw = bw = 0.1
+ self.bw = bw = 0.12
self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4)
times = xrange(100)
self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times)
diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i
index b7d3656bcf..aad96e5c86 100644
--- a/gr-filter/swig/filter_swig.i
+++ b/gr-filter/swig/filter_swig.i
@@ -30,8 +30,6 @@
%{
#include "gnuradio/filter/firdes.h"
#include "gnuradio/filter/pm_remez.h"
-#include "gnuradio/filter/adaptive_fir_ccc.h"
-#include "gnuradio/filter/adaptive_fir_ccf.h"
#include "gnuradio/filter/dc_blocker_cc.h"
#include "gnuradio/filter/dc_blocker_ff.h"
#include "gnuradio/filter/filter_delay_fc.h"
@@ -79,8 +77,6 @@
%include "gnuradio/filter/firdes.h"
%include "gnuradio/filter/pm_remez.h"
-%include "gnuradio/filter/adaptive_fir_ccc.h"
-%include "gnuradio/filter/adaptive_fir_ccf.h"
%include "gnuradio/filter/dc_blocker_cc.h"
%include "gnuradio/filter/dc_blocker_ff.h"
%include "gnuradio/filter/filter_delay_fc.h"
@@ -125,8 +121,6 @@
%include "gnuradio/filter/single_pole_iir_filter_cc.h"
%include "gnuradio/filter/single_pole_iir_filter_ff.h"
-GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccc);
-GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccf);
GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_cc);
GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_ff);
GR_SWIG_BLOCK_MAGIC2(filter, filter_delay_fc);
diff --git a/gr-noaa/python/noaa/CMakeLists.txt b/gr-noaa/python/noaa/CMakeLists.txt
index 27ed2e1abd..7b7ec4783c 100644
--- a/gr-noaa/python/noaa/CMakeLists.txt
+++ b/gr-noaa/python/noaa/CMakeLists.txt
@@ -44,6 +44,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-pager/python/pager/CMakeLists.txt b/gr-pager/python/pager/CMakeLists.txt
index 8502d1f88e..899c62e322 100644
--- a/gr-pager/python/pager/CMakeLists.txt
+++ b/gr-pager/python/pager/CMakeLists.txt
@@ -44,6 +44,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-qtgui/grc/qtgui_freq_sink_x.xml b/gr-qtgui/grc/qtgui_freq_sink_x.xml
index 35edf61ed8..6a61a05e0f 100644
--- a/gr-qtgui/grc/qtgui_freq_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_freq_sink_x.xml
@@ -78,6 +78,10 @@ $(gui_hint()($win))</make>
<name>Kaiser</name>
<key>firdes.WIN_KAISER</key>
</option>
+ <option>
+ <name>Flat-top</name>
+ <key>firdes.WIN_FLATTOP</key>
+ </option>
</param>
<param>
<name>Center Frequency (Hz)</name>
diff --git a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
index 176a907e9e..ac08450730 100644
--- a/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_waterfall_sink_x.xml
@@ -77,6 +77,10 @@ $(gui_hint()($win))</make>
<name>Kaiser</name>
<key>firdes.WIN_KAISER</key>
</option>
+ <option>
+ <name>Flat-top</name>
+ <key>firdes.WIN_FLATTOP</key>
+ </option>
</param>
<param>
<name>Center Frequency (Hz)</name>
diff --git a/gr-qtgui/include/gnuradio/qtgui/form_menus.h b/gr-qtgui/include/gnuradio/qtgui/form_menus.h
index d6499572c3..e7ebc3a797 100644
--- a/gr-qtgui/include/gnuradio/qtgui/form_menus.h
+++ b/gr-qtgui/include/gnuradio/qtgui/form_menus.h
@@ -26,6 +26,8 @@
#include <stdexcept>
#include <vector>
#include <QtGui/QtGui>
+#include <QtGui/QIntValidator>
+#include <QtGui/QDoubleValidator>
#include <qwt_symbol.h>
#include <gnuradio/filter/firdes.h>
#include <gnuradio/qtgui/qtgui_types.h>
@@ -498,6 +500,16 @@ public:
~OtherAction()
{}
+ void setValidator(QValidator *v)
+ {
+ d_text->setValidator(v);
+ }
+
+ void setDiagText(QString text)
+ {
+ d_text->setText(text);
+ }
+
signals:
void whichTrigger(const QString &text);
@@ -603,11 +615,20 @@ public:
d_act.push_back(new QAction("1024", this));
d_act.push_back(new QAction("2048", this));
d_act.push_back(new QAction("4096", this));
- d_act.push_back(new QAction("8192", this));
- d_act.push_back(new QAction("16384", this));
- d_act.push_back(new QAction("32768", this));
+ //d_act.push_back(new QAction("8192", this));
+ //d_act.push_back(new QAction("16384", this));
+ //d_act.push_back(new QAction("32768", this));
d_act.push_back(new OtherAction(this));
+ d_grp = new QActionGroup(this);
+ for(int t = 0; t < d_act.size(); t++) {
+ d_act[t]->setCheckable(true);
+ d_act[t]->setActionGroup(d_grp);
+ }
+
+ QIntValidator *valid = new QIntValidator(32, 4096, this);
+ ((OtherAction*)d_act[d_act.size()-1])->setValidator(valid);
+
connect(d_act[0], SIGNAL(triggered()), this, SLOT(get05()));
connect(d_act[1], SIGNAL(triggered()), this, SLOT(get06()));
connect(d_act[2], SIGNAL(triggered()), this, SLOT(get07()));
@@ -616,59 +637,78 @@ public:
connect(d_act[5], SIGNAL(triggered()), this, SLOT(get10()));
connect(d_act[6], SIGNAL(triggered()), this, SLOT(get11()));
connect(d_act[7], SIGNAL(triggered()), this, SLOT(get12()));
- connect(d_act[8], SIGNAL(triggered()), this, SLOT(get13()));
- connect(d_act[9], SIGNAL(triggered()), this, SLOT(get14()));
- connect(d_act[10], SIGNAL(triggered()), this, SLOT(get15()));
- connect(d_act[11], SIGNAL(whichTrigger(const QString&)),
- this, SLOT(getOther(const QString&)));
+ //connect(d_act[8], SIGNAL(triggered()), this, SLOT(get13()));
+ //connect(d_act[9], SIGNAL(triggered()), this, SLOT(get14()));
+ //connect(d_act[10], SIGNAL(triggered()), this, SLOT(get15()));
+ connect(d_act[8], SIGNAL(whichTrigger(const QString&)),
+ this, SLOT(getOther(const QString&)));
- QListIterator<QAction*> i(d_act);
- while(i.hasNext()) {
- QAction *a = i.next();
- addAction(a);
- }
- }
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
- ~FFTSizeMenu()
- {}
+ ~FFTSizeMenu()
+ {}
- int getNumActions() const
- {
- return d_act.size();
- }
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
- QAction * getAction(int which)
- {
- if(which < d_act.size())
- return d_act[which];
- else
- throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n");
- }
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n");
+ }
- signals:
- void whichTrigger(int size);
+ QAction * getActionFromSize(int size)
+ {
+ float ipt;
+ float which = logf(static_cast<float>(size))/logf(2.0) - 5;
+ // If we're a predefined value
+ if(modff(which,&ipt) == 0) {
+ if(which < d_act.size()-1)
+ return d_act[static_cast<int>(which)];
+ else
+ throw std::runtime_error("FFTSizeMenu::getActionFromString: which out of range.\n");
+ }
+ // Or a non-predefined value, return Other
+ else {
+ ((OtherAction*)d_act[d_act.size()-1])->setDiagText(QString().setNum(size));
+ return d_act[d_act.size()-1];
+ }
+ }
- public slots:
- void get05() { emit whichTrigger(32); }
- void get06() { emit whichTrigger(64); }
- void get07() { emit whichTrigger(128); }
- void get08() { emit whichTrigger(256); }
- void get09() { emit whichTrigger(512); }
- void get10() { emit whichTrigger(1024); }
- void get11() { emit whichTrigger(2048); }
- void get12() { emit whichTrigger(4096); }
- void get13() { emit whichTrigger(8192); }
- void get14() { emit whichTrigger(16384); }
- void get15() { emit whichTrigger(32768); }
- void getOther(const QString &str)
- {
- int value = str.toInt();
- emit whichTrigger(value);
- }
+signals:
+ void whichTrigger(int size);
+
+public slots:
+ void get05() { emit whichTrigger(32); }
+ void get06() { emit whichTrigger(64); }
+ void get07() { emit whichTrigger(128); }
+ void get08() { emit whichTrigger(256); }
+ void get09() { emit whichTrigger(512); }
+ void get10() { emit whichTrigger(1024); }
+ void get11() { emit whichTrigger(2048); }
+ void get12() { emit whichTrigger(4096); }
+ //void get13() { emit whichTrigger(8192); }
+ //void get14() { emit whichTrigger(16384); }
+ //void get15() { emit whichTrigger(32768); }
+ void getOther(const QString &str)
+ {
+ int value = str.toInt();
+ emit whichTrigger(value);
+ }
private:
QList<QAction *> d_act;
OtherAction *d_other;
+ QActionGroup *d_grp;
};
@@ -683,50 +723,83 @@ public:
FFTAverageMenu(QWidget *parent)
: QMenu("FFT Average", parent)
{
+ d_off = 1.0;
+ d_high = 0.05;
+ d_medium = 0.1;
+ d_low = 0.2;
+
d_act.push_back(new QAction("Off", this));
d_act.push_back(new QAction("High", this));
d_act.push_back(new QAction("Medium", this));
d_act.push_back(new QAction("Low", this));
d_act.push_back(new OtherAction(this));
+ d_grp = new QActionGroup(this);
+ for(int t = 0; t < d_act.size(); t++) {
+ d_act[t]->setCheckable(true);
+ d_act[t]->setActionGroup(d_grp);
+ }
+ d_act[0]->setChecked(true);
+
+ QDoubleValidator *valid = new QDoubleValidator(0.0, 1.0, 2, this);
+ ((OtherAction*)d_act[d_act.size()-1])->setValidator(valid);
+
connect(d_act[0], SIGNAL(triggered()), this, SLOT(getOff()));
connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHigh()));
connect(d_act[2], SIGNAL(triggered()), this, SLOT(getMedium()));
connect(d_act[3], SIGNAL(triggered()), this, SLOT(getLow()));
connect(d_act[4], SIGNAL(whichTrigger(const QString&)),
- this, SLOT(getOther(const QString&)));
+ this, SLOT(getOther(const QString&)));
- QListIterator<QAction*> i(d_act);
- while(i.hasNext()) {
- QAction *a = i.next();
- addAction(a);
- }
- }
+ QListIterator<QAction*> i(d_act);
+ while(i.hasNext()) {
+ QAction *a = i.next();
+ addAction(a);
+ }
+ }
- ~FFTAverageMenu()
- {}
+ ~FFTAverageMenu()
+ {}
- int getNumActions() const
- {
- return d_act.size();
- }
+ int getNumActions() const
+ {
+ return d_act.size();
+ }
- QAction * getAction(int which)
- {
- if(which < d_act.size())
- return d_act[which];
- else
- throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n");
- }
+ QAction * getAction(int which)
+ {
+ if(which < d_act.size())
+ return d_act[which];
+ else
+ throw std::runtime_error("FFTSizeMenu::getAction: which out of range.\n");
+ }
+
+ QAction * getActionFromAvg(float avg)
+ {
+ int which = 0;
+ if(avg == d_off)
+ which = 0;
+ else if(avg == d_high)
+ which = 1;
+ else if(avg == d_medium)
+ which = 2;
+ else if(avg == d_low)
+ which = 3;
+ else {
+ ((OtherAction*)d_act[d_act.size()-1])->setDiagText(QString().setNum(avg));
+ which = 4;
+ }
+ return d_act[static_cast<int>(which)];
+ }
signals:
void whichTrigger(float alpha);
public slots:
- void getOff() { emit whichTrigger(1.0); }
- void getHigh() { emit whichTrigger(0.05); }
- void getMedium() { emit whichTrigger(0.1); }
- void getLow() { emit whichTrigger(0.2); }
+ void getOff() { emit whichTrigger(d_off); }
+ void getHigh() { emit whichTrigger(d_high); }
+ void getMedium() { emit whichTrigger(d_medium); }
+ void getLow() { emit whichTrigger(d_low); }
void getOther(const QString &str)
{
float value = str.toFloat();
@@ -736,6 +809,8 @@ public:
private:
QList<QAction *> d_act;
OtherAction *d_other;
+ QActionGroup *d_grp;
+ float d_off, d_high, d_medium, d_low;
};
@@ -757,6 +832,13 @@ public:
d_act.push_back(new QAction("Blackman-harris", this));
d_act.push_back(new QAction("Rectangular", this));
d_act.push_back(new QAction("Kaiser", this));
+ d_act.push_back(new QAction("Flat-top", this));
+
+ d_grp = new QActionGroup(this);
+ for(int t = 0; t < d_act.size(); t++) {
+ d_act[t]->setCheckable(true);
+ d_act[t]->setActionGroup(d_grp);
+ }
connect(d_act[0], SIGNAL(triggered()), this, SLOT(getNone()));
connect(d_act[1], SIGNAL(triggered()), this, SLOT(getHamming()));
@@ -765,6 +847,7 @@ public:
connect(d_act[4], SIGNAL(triggered()), this, SLOT(getBlackmanharris()));
connect(d_act[5], SIGNAL(triggered()), this, SLOT(getRectangular()));
connect(d_act[6], SIGNAL(triggered()), this, SLOT(getKaiser()));
+ connect(d_act[7], SIGNAL(triggered()), this, SLOT(getFlattop()));
QListIterator<QAction*> i(d_act);
while(i.hasNext()) {
@@ -789,6 +872,22 @@ public:
throw std::runtime_error("FFTWindowMenu::getAction: which out of range.\n");
}
+ QAction * getActionFromWindow(gr::filter::firdes::win_type type)
+ {
+ int which = 0;
+ switch(static_cast<int>(type)) {
+ case((gr::filter::firdes::WIN_NONE)): which = 0; break;
+ case((gr::filter::firdes::WIN_HAMMING)): which = 1; break;
+ case((gr::filter::firdes::WIN_HANN)): which = 2; break;
+ case((gr::filter::firdes::WIN_BLACKMAN)): which = 3; break;
+ case((gr::filter::firdes::WIN_BLACKMAN_hARRIS)): which = 4; break;
+ case((gr::filter::firdes::WIN_RECTANGULAR)): which = 5; break;
+ case((gr::filter::firdes::WIN_KAISER)): which = 6; break;
+ case((gr::filter::firdes::WIN_FLATTOP)): which = 7; break;
+ }
+ return d_act[which];
+ }
+
signals:
void whichTrigger(const gr::filter::firdes::win_type type);
@@ -800,9 +899,11 @@ public slots:
void getBlackmanharris() { emit whichTrigger(gr::filter::firdes::WIN_BLACKMAN_hARRIS); }
void getRectangular() { emit whichTrigger(gr::filter::firdes::WIN_RECTANGULAR); }
void getKaiser() { emit whichTrigger(gr::filter::firdes::WIN_KAISER); }
+ void getFlattop() { emit whichTrigger(gr::filter::firdes::WIN_FLATTOP); }
private:
QList<QAction *> d_act;
+ QActionGroup *d_grp;
int d_which;
};
diff --git a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
index 9a69810276..95e6337f04 100644
--- a/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/freqdisplayform.h
@@ -73,6 +73,11 @@ private:
int d_fftsize;
float d_fftavg;
gr::filter::firdes::win_type d_fftwintype;
+
+ FFTSizeMenu *d_sizemenu;
+ FFTAverageMenu *d_avgmenu;
+ FFTWindowMenu *d_winmenu;
+
};
#endif /* FREQ_DISPLAY_FORM_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h
index 926d1cec12..1ac1cf428f 100644
--- a/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/waterfalldisplayform.h
@@ -92,6 +92,10 @@ private:
double d_min_val;
double d_max_val;
+
+ FFTSizeMenu *d_sizemenu;
+ FFTAverageMenu *d_avgmenu;
+ FFTWindowMenu *d_winmenu;
};
#endif /* WATERFALL_DISPLAY_FORM_H */
diff --git a/gr-qtgui/lib/freqdisplayform.cc b/gr-qtgui/lib/freqdisplayform.cc
index 46050d8149..32d82b9a8d 100644
--- a/gr-qtgui/lib/freqdisplayform.cc
+++ b/gr-qtgui/lib/freqdisplayform.cc
@@ -40,17 +40,17 @@ FreqDisplayForm::FreqDisplayForm(int nplots, QWidget* parent)
d_fftsize = 1024;
d_fftavg = 1.0;
- FFTSizeMenu *sizemenu = new FFTSizeMenu(this);
- FFTAverageMenu *avgmenu = new FFTAverageMenu(this);
- FFTWindowMenu *winmenu = new FFTWindowMenu(this);
- d_menu->addMenu(sizemenu);
- d_menu->addMenu(avgmenu);
- d_menu->addMenu(winmenu);
- connect(sizemenu, SIGNAL(whichTrigger(int)),
+ d_sizemenu = new FFTSizeMenu(this);
+ d_avgmenu = new FFTAverageMenu(this);
+ d_winmenu = new FFTWindowMenu(this);
+ d_menu->addMenu(d_sizemenu);
+ d_menu->addMenu(d_avgmenu);
+ d_menu->addMenu(d_winmenu);
+ connect(d_sizemenu, SIGNAL(whichTrigger(int)),
this, SLOT(setFFTSize(const int)));
- connect(avgmenu, SIGNAL(whichTrigger(float)),
+ connect(d_avgmenu, SIGNAL(whichTrigger(float)),
this, SLOT(setFFTAverage(const float)));
- connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
+ connect(d_winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
this, SLOT(setFFTWindowType(const gr::filter::firdes::win_type)));
Reset();
@@ -120,6 +120,7 @@ void
FreqDisplayForm::setFFTSize(const int newsize)
{
d_fftsize = newsize;
+ d_sizemenu->getActionFromSize(newsize)->setChecked(true);
getPlot()->replot();
}
@@ -127,6 +128,7 @@ void
FreqDisplayForm::setFFTAverage(const float newavg)
{
d_fftavg = newavg;
+ d_avgmenu->getActionFromAvg(newavg)->setChecked(true);
getPlot()->replot();
}
@@ -134,6 +136,7 @@ void
FreqDisplayForm::setFFTWindowType(const gr::filter::firdes::win_type newwin)
{
d_fftwintype = newwin;
+ d_winmenu->getActionFromWindow(newwin)->setChecked(true);
getPlot()->replot();
}
diff --git a/gr-qtgui/lib/waterfalldisplayform.cc b/gr-qtgui/lib/waterfalldisplayform.cc
index 4b8e042658..f4dd2fd338 100644
--- a/gr-qtgui/lib/waterfalldisplayform.cc
+++ b/gr-qtgui/lib/waterfalldisplayform.cc
@@ -75,17 +75,17 @@ WaterfallDisplayForm::WaterfallDisplayForm(int nplots, QWidget* parent)
d_autoscale_act->setText(tr("Auto Scale"));
d_autoscale_act->setCheckable(false);
- FFTSizeMenu *sizemenu = new FFTSizeMenu(this);
- FFTAverageMenu *avgmenu = new FFTAverageMenu(this);
- FFTWindowMenu *winmenu = new FFTWindowMenu(this);
- d_menu->addMenu(sizemenu);
- d_menu->addMenu(avgmenu);
- d_menu->addMenu(winmenu);
- connect(sizemenu, SIGNAL(whichTrigger(int)),
+ d_sizemenu = new FFTSizeMenu(this);
+ d_avgmenu = new FFTAverageMenu(this);
+ d_winmenu = new FFTWindowMenu(this);
+ d_menu->addMenu(d_sizemenu);
+ d_menu->addMenu(d_avgmenu);
+ d_menu->addMenu(d_winmenu);
+ connect(d_sizemenu, SIGNAL(whichTrigger(int)),
this, SLOT(setFFTSize(const int)));
- connect(avgmenu, SIGNAL(whichTrigger(float)),
+ connect(d_avgmenu, SIGNAL(whichTrigger(float)),
this, SLOT(setFFTAverage(const float)));
- connect(winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
+ connect(d_winmenu, SIGNAL(whichTrigger(gr::filter::firdes::win_type)),
this, SLOT(setFFTWindowType(const gr::filter::firdes::win_type)));
Reset();
@@ -190,18 +190,24 @@ void
WaterfallDisplayForm::setFFTSize(const int newsize)
{
d_fftsize = newsize;
+ d_sizemenu->getActionFromSize(newsize)->setChecked(true);
+ getPlot()->replot();
}
void
WaterfallDisplayForm::setFFTAverage(const float newavg)
{
d_fftavg = newavg;
+ d_avgmenu->getActionFromAvg(newavg)->setChecked(true);
+ getPlot()->replot();
}
void
WaterfallDisplayForm::setFFTWindowType(const gr::filter::firdes::win_type newwin)
{
d_fftwintype = newwin;
+ d_winmenu->getActionFromWindow(newwin)->setChecked(true);
+ getPlot()->replot();
}
void
diff --git a/gr-qtgui/python/qtgui/CMakeLists.txt b/gr-qtgui/python/qtgui/CMakeLists.txt
index 3efc8f45b5..8fcbac68a3 100644
--- a/gr-qtgui/python/qtgui/CMakeLists.txt
+++ b/gr-qtgui/python/qtgui/CMakeLists.txt
@@ -41,6 +41,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-trellis/python/trellis/CMakeLists.txt b/gr-trellis/python/trellis/CMakeLists.txt
index 2d5e2ad94a..b4223af935 100644
--- a/gr-trellis/python/trellis/CMakeLists.txt
+++ b/gr-trellis/python/trellis/CMakeLists.txt
@@ -44,6 +44,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-uhd/python/uhd/CMakeLists.txt b/gr-uhd/python/uhd/CMakeLists.txt
index ac113fe2d2..aa1d1a6b4a 100644
--- a/gr-uhd/python/uhd/CMakeLists.txt
+++ b/gr-uhd/python/uhd/CMakeLists.txt
@@ -45,6 +45,6 @@ include(GrTest)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-utils/python/modtool/CMakeLists.txt b/gr-utils/python/modtool/CMakeLists.txt
index d7816816c3..bb4febe318 100644
--- a/gr-utils/python/modtool/CMakeLists.txt
+++ b/gr-utils/python/modtool/CMakeLists.txt
@@ -33,6 +33,7 @@ GR_PYTHON_INSTALL(FILES
modtool_newmod.py
modtool_rm.py
parser_cc_block.py
+ scm.py
templates.py
util_functions.py
DESTINATION ${GR_PYTHON_DIR}/gnuradio/modtool
diff --git a/gr-utils/python/modtool/__init__.py b/gr-utils/python/modtool/__init__.py
index a242722ab4..a6a022a202 100644
--- a/gr-utils/python/modtool/__init__.py
+++ b/gr-utils/python/modtool/__init__.py
@@ -22,13 +22,14 @@
from cmakefile_editor import CMakeFileEditor
from code_generator import GRMTemplate
from grc_xml_generator import GRCXMLGenerator
-from modtool_base import ModTool, get_class_dict
+from modtool_base import ModTool, ModToolException, get_class_dict
from modtool_add import ModToolAdd
from modtool_disable import ModToolDisable
from modtool_info import ModToolInfo
from modtool_makexml import ModToolMakeXML
from modtool_newmod import ModToolNewModule
from modtool_rm import ModToolRemove
+from templates import Templates
# Leave this at the end
from modtool_help import ModToolHelp
from parser_cc_block import ParserCCBlock
diff --git a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt
index 2dac3461a8..1d2e37b6a6 100644
--- a/gr-utils/python/modtool/gr-newmod/CMakeLists.txt
+++ b/gr-utils/python/modtool/gr-newmod/CMakeLists.txt
@@ -83,20 +83,15 @@ set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
########################################################################
# Find gnuradio build dependencies
########################################################################
-find_package(GnuradioRuntime)
find_package(CppUnit)
-# To run a more advanced search for GNU Radio and it's components and
-# versions, use the following. Add any components required to the list
-# of GR_REQUIRED_COMPONENTS (in all caps) and change "version" to the
-# minimum API compatible version required.
-#
-# set(GR_REQUIRED_COMPONENTS RUNTIME BLOCKS FILTER ...)
-# find_package(Gnuradio "version")
+# Search for GNU Radio and its components and versions. Add any
+# components required to the list of GR_REQUIRED_COMPONENTS (in all
+# caps such as FILTER or FFT) and change the version to the minimum
+# API compatible version required.
+set(GR_REQUIRED_COMPONENTS RUNTIME)
+find_package(Gnuradio "3.7.2" REQUIRED)
-if(NOT GNURADIO_RUNTIME_FOUND)
- message(FATAL_ERROR "GnuRadio Runtime required to compile howto")
-endif()
if(NOT CPPUNIT_FOUND)
message(FATAL_ERROR "CppUnit required to compile howto")
endif()
@@ -111,7 +106,7 @@ include_directories(
${CMAKE_BINARY_DIR}/include
${Boost_INCLUDE_DIRS}
${CPPUNIT_INCLUDE_DIRS}
- ${GNURADIO_RUNTIME_INCLUDE_DIRS}
+ ${GNURADIO_ALL_INCLUDE_DIRS}
)
link_directories(
diff --git a/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt b/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt
index 312594149c..de53723de2 100644
--- a/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt
+++ b/gr-utils/python/modtool/gr-newmod/lib/CMakeLists.txt
@@ -29,7 +29,7 @@ list(APPEND howto_sources
)
add_library(gnuradio-howto SHARED ${howto_sources})
-target_link_libraries(gnuradio-howto ${Boost_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES})
+target_link_libraries(gnuradio-howto ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES})
set_target_properties(gnuradio-howto PROPERTIES DEFINE_SYMBOL "gnuradio_howto_EXPORTS")
########################################################################
diff --git a/gr-utils/python/modtool/modtool_add.py b/gr-utils/python/modtool/modtool_add.py
index 88b9068cda..e188b7fd71 100644
--- a/gr-utils/python/modtool/modtool_add.py
+++ b/gr-utils/python/modtool/modtool_add.py
@@ -21,27 +21,30 @@
""" Module to add new blocks """
import os
-import sys
import re
from optparse import OptionGroup
from util_functions import append_re_line_sequence, ask_yes_no
from cmakefile_editor import CMakeFileEditor
-from modtool_base import ModTool
+from modtool_base import ModTool, ModToolException
from templates import Templates
from code_generator import get_template
import Cheetah.Template
+
class ModToolAdd(ModTool):
""" Add block to the out-of-tree module. """
name = 'add'
aliases = ('insert',)
_block_types = ('sink', 'source', 'sync', 'decimator', 'interpolator',
'general', 'tagged_stream', 'hier', 'noblock')
+
def __init__(self):
ModTool.__init__(self)
self._add_cc_qa = False
self._add_py_qa = False
+ self._skip_cmakefiles = False
+ self._license_file = None
def setup_parser(self):
parser = ModTool.setup_parser(self)
@@ -63,9 +66,9 @@ class ModToolAdd(ModTool):
parser.add_option_group(ogroup)
return parser
- def setup(self):
- ModTool.setup(self)
- options = self.options
+ def setup(self, options, args):
+ ModTool.setup(self, options, args)
+
self._info['blocktype'] = options.block_type
if self._info['blocktype'] is None:
while self._info['blocktype'] not in self._block_types:
@@ -79,17 +82,15 @@ class ModToolAdd(ModTool):
if ((self._skip_subdirs['lib'] and self._info['lang'] == 'cpp')
or (self._skip_subdirs['python'] and self._info['lang'] == 'python')):
- print "Missing or skipping relevant subdir."
- exit(1)
+ raise ModToolException('Missing or skipping relevant subdir.')
if self._info['blockname'] is None:
- if len(self.args) >= 2:
- self._info['blockname'] = self.args[1]
+ if len(args) >= 2:
+ self._info['blockname'] = args[1]
else:
self._info['blockname'] = raw_input("Enter name of block/code (without module name prefix): ")
if not re.match('[a-zA-Z0-9_]+', self._info['blockname']):
- print 'Invalid block name.'
- exit(2)
+ raise ModToolException('Invalid block name.')
print "Block/code identifier: " + self._info['blockname']
self._info['fullblockname'] = self._info['modname'] + '_' + self._info['blockname']
self._info['license'] = self.setup_choose_license()
@@ -107,11 +108,12 @@ class ModToolAdd(ModTool):
self._add_cc_qa = options.add_cpp_qa
if self._add_cc_qa is None:
self._add_cc_qa = ask_yes_no('Add C++ QA code?', not self._add_py_qa)
- if self._info['version'] == 'autofoo' and not self.options.skip_cmakefiles:
+ self._skip_cmakefiles = options.skip_cmakefiles
+ if self._info['version'] == 'autofoo' and not self._skip_cmakefiles:
print "Warning: Autotools modules are not supported. ",
print "Files will be created, but Makefiles will not be edited."
- self.options.skip_cmakefiles = True
-
+ 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:
@@ -119,9 +121,9 @@ class ModToolAdd(ModTool):
2) The contents of the file LICENSE or LICENCE in the modules
top directory
3) The default license. """
- if self.options.license_file is not None \
- and os.path.isfile(self.options.license_file):
- return open(self.options.license_file).read()
+ if self._license_file is not None \
+ and os.path.isfile(self._license_file):
+ return open(self._license_file).read()
elif os.path.isfile('LICENSE'):
return open('LICENSE').read()
elif os.path.isfile('LICENCE'):
@@ -133,8 +135,10 @@ class ModToolAdd(ModTool):
def _write_tpl(self, tpl, path, fname):
""" Shorthand for writing a substituted template to a file"""
- print "Adding file '%s'..." % fname
- open(os.path.join(path, fname), 'w').write(get_template(tpl, **self._info))
+ path_to_file = os.path.join(path, fname)
+ print "Adding file '%s'..." % path_to_file
+ open(path_to_file, 'w').write(get_template(tpl, **self._info))
+ self.scm.add_files((path_to_file,))
def run(self):
""" Go, go, go. """
@@ -170,7 +174,7 @@ class ModToolAdd(ModTool):
fname_qa_cc = 'qa_%s.cc' % self._info['blockname']
self._write_tpl('qa_cpp', 'lib', fname_qa_cc)
self._write_tpl('qa_h', 'lib', fname_qa_h)
- if not self.options.skip_cmakefiles:
+ if not self._skip_cmakefiles:
try:
append_re_line_sequence(self._file['cmlib'],
'\$\{CMAKE_CURRENT_SOURCE_DIR\}/qa_%s.cc.*\n' % self._info['modname'],
@@ -183,24 +187,25 @@ class ModToolAdd(ModTool):
' s->addTest(gr::%s::qa_%s::suite());' % (self._info['modname'],
self._info['blockname'])
)
+ self.scm.mark_files_updated((self._file['qalib'],))
except IOError:
print "Can't add C++ QA files."
def _add_qa36():
" Add C++ QA files for pre-3.7 API (not autotools) "
fname_qa_cc = 'qa_%s.cc' % self._info['fullblockname']
self._write_tpl('qa_cpp36', 'lib', fname_qa_cc)
- if not self.options.skip_cmakefiles:
+ if not self._skip_cmakefiles:
open(self._file['cmlib'], 'a').write(
- str(
- Cheetah.Template.Template(
- Templates['qa_cmakeentry36'],
- searchList={'basename': os.path.splitext(fname_qa_cc)[0],
- 'upperbasename': os.path.splitext(fname_qa_cc)[0].upper(),
- 'filename': fname_qa_cc,
- 'modname': self._info['modname']
- }
- )
- )
+ str(
+ Cheetah.Template.Template(
+ Templates['qa_cmakeentry36'],
+ searchList={'basename': os.path.splitext(fname_qa_cc)[0],
+ 'upperbasename': os.path.splitext(fname_qa_cc)[0].upper(),
+ 'filename': fname_qa_cc,
+ 'modname': self._info['modname']
+ }
+ )
+ )
)
ed = CMakeFileEditor(self._file['cmlib'])
ed.remove_double_newlines()
@@ -221,7 +226,14 @@ class ModToolAdd(ModTool):
fname_cc = self._info['fullblockname'] + '.cc'
self._write_tpl('block_h36', self._info['includedir'], fname_h)
self._write_tpl('block_cpp36', 'lib', fname_cc)
- if not self.options.skip_cmakefiles:
+ if self._add_cc_qa:
+ if self._info['version'] == '37':
+ _add_qa()
+ elif self._info['version'] == '36':
+ _add_qa36()
+ elif self._info['version'] == 'autofoo':
+ print "Warning: C++ QA files not supported for autotools."
+ if not self._skip_cmakefiles:
ed = CMakeFileEditor(self._file['cmlib'])
cmake_list_var = '[a-z]*_?' + self._info['modname'] + '_sources'
if not ed.append_value('list', fname_cc, to_ignore_start='APPEND ' + cmake_list_var):
@@ -230,13 +242,7 @@ class ModToolAdd(ModTool):
ed = CMakeFileEditor(self._file['cminclude'])
ed.append_value('install', fname_h, to_ignore_end='DESTINATION[^()]+')
ed.write()
- if self._add_cc_qa:
- if self._info['version'] == '37':
- _add_qa()
- elif self._info['version'] == '36':
- _add_qa36()
- elif self._info['version'] == 'autofoo':
- print "Warning: C++ QA files not supported for autotools."
+ self.scm.mark_files_updated((self._file['cminclude'], self._file['cmlib']))
def _run_swig(self):
""" Do everything that needs doing in the subdir 'swig'.
@@ -262,6 +268,7 @@ class ModToolAdd(ModTool):
regexp = re.compile('^%\{\n', re.MULTILINE)
oldfile = regexp.sub('%%{\n%s\n' % include_str, oldfile, count=1)
open(self._file['swig'], 'w').write(oldfile)
+ self.scm.mark_files_updated((self._file['swig'],))
def _run_python_qa(self):
""" Do everything that needs doing in the subdir 'python' to add
@@ -272,12 +279,14 @@ class ModToolAdd(ModTool):
fname_py_qa = 'qa_' + self._info['blockname'] + '.py'
self._write_tpl('qa_python', self._info['pydir'], fname_py_qa)
os.chmod(os.path.join(self._info['pydir'], fname_py_qa), 0755)
- if self.options.skip_cmakefiles or CMakeFileEditor(self._file['cmpython']).check_for_glob('qa_*.py'):
+ self.scm.mark_files_updated((os.path.join(self._info['pydir'], fname_py_qa),))
+ if self._skip_cmakefiles or CMakeFileEditor(self._file['cmpython']).check_for_glob('qa_*.py'):
return
print "Editing %s/CMakeLists.txt..." % self._info['pydir']
open(self._file['cmpython'], 'a').write(
'GR_ADD_TEST(qa_%s ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/%s)\n' % \
(self._info['blockname'], fname_py_qa))
+ self.scm.mark_files_updated((self._file['cmpython'],))
def _run_python(self):
""" Do everything that needs doing in the subdir 'python' to add
@@ -291,11 +300,13 @@ class ModToolAdd(ModTool):
append_re_line_sequence(self._file['pyinit'],
'(^from.*import.*\n|# import any pure.*\n)',
'from %s import %s' % (self._info['blockname'], self._info['blockname']))
- if self.options.skip_cmakefiles:
+ self.scm.mark_files_updated((self._file['pyinit'],))
+ if self._skip_cmakefiles:
return
ed = CMakeFileEditor(self._file['cmpython'])
ed.append_value('GR_PYTHON_INSTALL', fname_py, to_ignore_end='DESTINATION[^()]+')
ed.write()
+ self.scm.mark_files_updated((self._file['cmpython'],))
def _run_grc(self):
""" Do everything that needs doing in the subdir 'grc' to add
@@ -306,9 +317,10 @@ class ModToolAdd(ModTool):
fname_grc = self._info['fullblockname'] + '.xml'
self._write_tpl('grc_xml', 'grc', fname_grc)
ed = CMakeFileEditor(self._file['cmgrc'], '\n ')
- if self.options.skip_cmakefiles or ed.check_for_glob('*.xml'):
+ if self._skip_cmakefiles or ed.check_for_glob('*.xml'):
return
print "Editing grc/CMakeLists.txt..."
ed.append_value('install', fname_grc, to_ignore_end='DESTINATION[^()]+')
ed.write()
+ self.scm.mark_files_updated((self._file['cmgrc'],))
diff --git a/gr-utils/python/modtool/modtool_base.py b/gr-utils/python/modtool/modtool_base.py
index f8fc8639c4..a58b7abcb1 100644
--- a/gr-utils/python/modtool/modtool_base.py
+++ b/gr-utils/python/modtool/modtool_base.py
@@ -22,15 +22,19 @@
import os
import re
-import sys
from optparse import OptionParser, OptionGroup
+from gnuradio import gr
from util_functions import get_modname
-from templates import Templates
+from scm import SCMRepoFactory
+class ModToolException(BaseException):
+ """ Standard exception for modtool classes. """
+ pass
class ModTool(object):
""" Base class for all modtool command classes. """
+ name = 'base'
def __init__(self):
self._subdirs = ['lib', 'include', 'python', 'swig', 'grc'] # List subdirs where stuff happens
self._has_subdirs = {}
@@ -41,8 +45,6 @@ class ModTool(object):
self._has_subdirs[subdir] = False
self._skip_subdirs[subdir] = False
self.parser = self.setup_parser()
- self.args = None
- self.options = None
self._dir = None
def setup_parser(self):
@@ -67,25 +69,25 @@ class ModTool(object):
help="Don't do anything in the python/ subdirectory.")
ogroup.add_option("--skip-grc", action="store_true", default=False,
help="Don't do anything in the grc/ subdirectory.")
+ ogroup.add_option("--scm-mode", type="choice", choices=('yes', 'no', 'auto'),
+ default=gr.prefs().get_string('modtool', 'scm_mode', 'no'),
+ help="Use source control management (yes, no or auto).")
ogroup.add_option("-y", "--yes", action="store_true", default=False,
help="Answer all questions with 'yes'. This can overwrite and delete your files, so be careful.")
parser.add_option_group(ogroup)
return parser
- def setup(self):
+ def setup(self, options, args):
""" Initialise all internal variables, such as the module name etc. """
- (options, self.args) = self.parser.parse_args()
self._dir = options.directory
if not self._check_directory(self._dir):
- print "No GNU Radio module found in the given directory. Quitting."
- sys.exit(1)
+ raise ModToolException('No GNU Radio module found in the given directory.')
if options.module_name is not None:
self._info['modname'] = options.module_name
else:
self._info['modname'] = get_modname()
if self._info['modname'] is None:
- print "No GNU Radio module found in the given directory. Quitting."
- sys.exit(1)
+ raise ModToolException('No GNU Radio module found in the given directory.')
print "GNU Radio module name identified: " + self._info['modname']
if self._info['version'] == '36' and (
os.path.isdir(os.path.join('include', self._info['modname'])) or
@@ -101,9 +103,10 @@ class ModTool(object):
if options.skip_grc or not self._has_subdirs['grc']:
self._skip_subdirs['grc'] = True
self._info['blockname'] = options.block_name
- self.options = options
self._setup_files()
self._info['yes'] = options.yes
+ self.options = options
+ self._setup_scm()
def _setup_files(self):
""" Initialise the self._file[] dictionary """
@@ -127,6 +130,17 @@ class ModTool(object):
self._file['cmswig'] = os.path.join('swig', 'CMakeLists.txt')
self._file['cmfind'] = os.path.join('cmake', 'Modules', 'howtoConfig.cmake')
+
+ def _setup_scm(self, mode='active'):
+ """ Initialize source control management. """
+ if mode == 'active':
+ self.scm = SCMRepoFactory(self.options, '.').make_active_scm_manager()
+ else:
+ self.scm = SCMRepoFactory(self.options, '.').make_empty_scm_manager()
+ if self.scm is None:
+ print "Error: Can't set up SCM."
+ exit(1)
+
def _check_directory(self, directory):
""" Guesses if dir is a valid GNU Radio module directory by looking for
CMakeLists.txt and at least one of the subdirs lib/, python/ and swig/.
@@ -141,8 +155,7 @@ class ModTool(object):
self._info['is_component'] = False
for f in files:
if os.path.isfile(f) and f == 'CMakeLists.txt':
- if re.search('find_package\(GnuradioRuntime\)', open(f).read()) is not None or \
- re.search('find_package\(Gnuradio(\s+[0-9".]+)?\)', open(f).read()) is not None:
+ if re.search('find_package\(Gnuradio', open(f).read()) is not None:
self._info['version'] = '36' # Might be 37, check that later
has_makefile = True
elif re.search('GR_REGISTER_COMPONENT', open(f).read()) is not None:
@@ -172,6 +185,7 @@ class ModTool(object):
""" Override this. """
pass
+
def get_class_dict(the_globals):
" Return a dictionary of the available commands in the form command->class "
classdict = {}
diff --git a/gr-utils/python/modtool/modtool_disable.py b/gr-utils/python/modtool/modtool_disable.py
index 36725e5578..4ae2242f99 100644
--- a/gr-utils/python/modtool/modtool_disable.py
+++ b/gr-utils/python/modtool/modtool_disable.py
@@ -23,25 +23,26 @@
import os
import re
import sys
-from optparse import OptionGroup
from modtool_base import ModTool
from cmakefile_editor import CMakeFileEditor
+
class ModToolDisable(ModTool):
""" Disable block (comments out CMake entries for files) """
name = 'disable'
aliases = ('dis',)
+
def __init__(self):
ModTool.__init__(self)
- def setup(self):
- ModTool.setup(self)
- options = self.options
+ def setup(self, options, args):
+ ModTool.setup(self, options, args)
+
if options.block_name is not None:
self._info['pattern'] = options.block_name
- elif len(self.args) >= 2:
- self._info['pattern'] = self.args[1]
+ elif len(args) >= 2:
+ self._info['pattern'] = args[1]
else:
self._info['pattern'] = raw_input('Which blocks do you want to disable? (Regex): ')
if len(self._info['pattern']) == 0:
@@ -52,6 +53,7 @@ class ModToolDisable(ModTool):
def _handle_py_qa(cmake, fname):
""" Do stuff for py qa """
cmake.comment_out_lines('GR_ADD_TEST.*'+fname)
+ self.scm.mark_file_updated(cmake.filename)
return True
def _handle_py_mod(cmake, fname):
""" Do stuff for py extra files """
@@ -63,6 +65,7 @@ class ModToolDisable(ModTool):
pymodname = os.path.splitext(fname)[0]
initfile = re.sub(r'((from|import)\s+\b'+pymodname+r'\b)', r'#\1', initfile)
open(self._file['pyinit'], 'w').write(initfile)
+ self.scm.mark_file_updated(self._file['pyinit'])
return False
def _handle_cc_qa(cmake, fname):
""" Do stuff for cc qa """
@@ -73,10 +76,12 @@ class ModToolDisable(ModTool):
ed.comment_out_lines('#include\s+"%s.h"' % fname_base, comment_str='//')
ed.comment_out_lines('%s::suite\(\)' % fname_base, comment_str='//')
ed.write()
+ self.scm.mark_file_updated(self._file['qalib'])
elif self._info['version'] == '36':
cmake.comment_out_lines('add_executable.*'+fname)
cmake.comment_out_lines('target_link_libraries.*'+os.path.splitext(fname)[0])
cmake.comment_out_lines('GR_ADD_TEST.*'+os.path.splitext(fname)[0])
+ self.scm.mark_file_updated(cmake.filename)
return True
def _handle_h_swig(cmake, fname):
""" Comment out include files from the SWIG file,
@@ -95,6 +100,7 @@ class ModToolDisable(ModTool):
if nsubs > 1:
print "Hm, changed more then expected while editing %s." % self._file['swig']
open(self._file['swig'], 'w').write(swigfile)
+ self.scm.mark_file_updated(self._file['swig'])
return False
def _handle_i_swig(cmake, fname):
""" Comment out include files from the SWIG file,
@@ -107,6 +113,7 @@ class ModToolDisable(ModTool):
print "Changing %s..." % self._file['swig']
swigfile = re.sub('(GR_SWIG_BLOCK_MAGIC2?.+'+blockname+'.+;)', r'//\1', swigfile)
open(self._file['swig'], 'w').write(swigfile)
+ self.scm.mark_file_updated(self._file['swig'])
return False
# List of special rules: 0: subdir, 1: filename re match, 2: callback
special_treatments = (
@@ -144,5 +151,6 @@ class ModToolDisable(ModTool):
if not file_disabled:
cmake.disable_file(fname)
cmake.write()
+ self.scm.mark_files_updated((os.path.join(subdir, 'CMakeLists.txt'),))
print "Careful: 'gr_modtool disable' does not resolve dependencies."
diff --git a/gr-utils/python/modtool/modtool_help.py b/gr-utils/python/modtool/modtool_help.py
index 76d9fd28bd..b894e272e8 100644
--- a/gr-utils/python/modtool/modtool_help.py
+++ b/gr-utils/python/modtool/modtool_help.py
@@ -26,8 +26,8 @@ from templates import Templates
def print_class_descriptions():
- ''' Go through all ModTool* classes and print their name,
- alias and description. '''
+ """ Go through all ModTool* classes and print their name,
+ alias and description. """
desclist = []
for gvar in globals().values():
try:
@@ -40,14 +40,16 @@ def print_class_descriptions():
for description in desclist:
print '%-8s %-12s %s' % description
+
class ModToolHelp(ModTool):
- ''' Show some help. '''
+ """ Show some help. """
name = 'help'
aliases = ('h', '?')
+
def __init__(self):
ModTool.__init__(self)
- def setup(self):
+ def setup(self, options, args):
pass
def run(self):
diff --git a/gr-utils/python/modtool/modtool_info.py b/gr-utils/python/modtool/modtool_info.py
index 3b392a3102..4c7480d698 100644
--- a/gr-utils/python/modtool/modtool_info.py
+++ b/gr-utils/python/modtool/modtool_info.py
@@ -23,18 +23,23 @@
import os
from optparse import OptionGroup
-from modtool_base import ModTool
+from modtool_base import ModTool, ModToolException
from util_functions import get_modname
+
class ModToolInfo(ModTool):
""" Return information about a given module """
name = 'info'
aliases = ('getinfo', 'inf')
+
def __init__(self):
ModTool.__init__(self)
+ self._directory = None
+ self._python_readable = False
+ self._suggested_dirs = None
def setup_parser(self):
- " Initialise the option parser for 'gr_modtool info' "
+ """ Initialise the option parser for 'gr_modtool info' """
parser = ModTool.setup_parser(self)
parser.usage = '%prog info [options]. \n Call %prog without any options to run it interactively.'
ogroup = OptionGroup(parser, "Info options")
@@ -45,28 +50,22 @@ class ModToolInfo(ModTool):
parser.add_option_group(ogroup)
return parser
- def setup(self):
+ def setup(self, options, args):
# Won't call parent's setup(), because that's too chatty
- (self.options, self.args) = self.parser.parse_args()
+ self._directory = options.directory
+ self._python_readable = options.python_readable
+ self._suggested_dirs = options.suggested_dirs
def run(self):
""" Go, go, go! """
- mod_info = {}
- mod_info['base_dir'] = self._get_base_dir(self.options.directory)
+ mod_info = dict()
+ mod_info['base_dir'] = self._get_base_dir(self._directory)
if mod_info['base_dir'] is None:
- if self.options.python_readable:
- print '{}'
- else:
- print "No module found."
- exit(1)
+ raise ModToolException('{}' if self._python_readable else "No module found.")
os.chdir(mod_info['base_dir'])
mod_info['modname'] = get_modname()
if mod_info['modname'] is None:
- if self.options.python_readable:
- print '{}'
- else:
- print "No module found."
- exit(1)
+ raise ModToolException('{}' if self._python_readable else "No module found.")
if self._info['version'] == '36' and (
os.path.isdir(os.path.join('include', mod_info['modname'])) or
os.path.isdir(os.path.join('include', 'gnuradio', mod_info['modname']))
@@ -85,7 +84,7 @@ class ModToolInfo(ModTool):
if build_dir is not None:
mod_info['build_dir'] = build_dir
mod_info['incdirs'] += self._get_include_dirs(mod_info)
- if self.options.python_readable:
+ if self._python_readable:
print str(mod_info)
else:
self._pretty_print(mod_info)
@@ -134,8 +133,8 @@ class ModToolInfo(ModTool):
inc_dirs += line.replace('GNURADIO_RUNTIME_INCLUDE_DIRS:%s=' % path_or_internal, '').strip().split(';')
except IOError:
pass
- if len(inc_dirs) == 0 and self.options.suggested_dirs is not None:
- inc_dirs = [os.path.normpath(path) for path in self.options.suggested_dirs.split(':') if os.path.isdir(path)]
+ if len(inc_dirs) == 0 and self._suggested_dirs is not None:
+ inc_dirs = [os.path.normpath(path) for path in self._suggested_dirs.split(':') if os.path.isdir(path)]
return inc_dirs
def _pretty_print(self, mod_info):
@@ -154,4 +153,3 @@ class ModToolInfo(ModTool):
}[mod_info['version']]
else:
print '%19s: %s' % (index_names[key], mod_info[key])
-
diff --git a/gr-utils/python/modtool/modtool_makexml.py b/gr-utils/python/modtool/modtool_makexml.py
index 777cc09e1f..28eabe1b81 100644
--- a/gr-utils/python/modtool/modtool_makexml.py
+++ b/gr-utils/python/modtool/modtool_makexml.py
@@ -20,32 +20,32 @@
#
""" Automatically create XML bindings for GRC from block code """
-import sys
import os
import re
import glob
-from optparse import OptionGroup
-from modtool_base import ModTool
+from modtool_base import ModTool, ModToolException
from parser_cc_block import ParserCCBlock
from grc_xml_generator import GRCXMLGenerator
from cmakefile_editor import CMakeFileEditor
from util_functions import ask_yes_no
+
class ModToolMakeXML(ModTool):
""" Make XML file for GRC block bindings """
name = 'makexml'
aliases = ('mx',)
+
def __init__(self):
ModTool.__init__(self)
- def setup(self):
- ModTool.setup(self)
- options = self.options
+ def setup(self, options, args):
+ ModTool.setup(self, options, args)
+
if options.block_name is not None:
self._info['pattern'] = options.block_name
- elif len(self.args) >= 2:
- self._info['pattern'] = self.args[1]
+ elif len(args) >= 2:
+ self._info['pattern'] = args[1]
else:
self._info['pattern'] = raw_input('Which blocks do you want to parse? (Regex): ')
if len(self._info['pattern']) == 0:
@@ -66,7 +66,7 @@ class ModToolMakeXML(ModTool):
(params, iosig, blockname) = self._parse_cc_h(f)
self._make_grc_xml_from_block_data(params, iosig, blockname)
# 2) Go through python/
-
+ # TODO
def _search_files(self, path, path_glob):
""" Search for files matching pattern in the given path. """
@@ -85,6 +85,7 @@ class ModToolMakeXML(ModTool):
generator. Also, check the makefile if the .xml file is in there.
If necessary, add. """
fname_xml = '%s_%s.xml' % (self._info['modname'], blockname)
+ path_to_xml = os.path.join('grc', fname_xml)
# Some adaptions for the GRC
for inout in ('in', 'out'):
if iosig[inout]['max_ports'] == '-1':
@@ -94,11 +95,13 @@ class ModToolMakeXML(ModTool):
'name': 'Num %sputs' % inout,
'default': '2',
'in_constructor': False})
- if os.path.isfile(os.path.join('grc', fname_xml)):
+ file_exists = False
+ if os.path.isfile(path_to_xml):
if not self._info['yes']:
if not ask_yes_no('Overwrite existing GRC file?', False):
return
else:
+ file_exists = True
print "Warning: Overwriting existing GRC file."
grc_generator = GRCXMLGenerator(
modname=self._info['modname'],
@@ -106,13 +109,18 @@ class ModToolMakeXML(ModTool):
params=params,
iosig=iosig
)
- grc_generator.save(os.path.join('grc', fname_xml))
+ grc_generator.save(path_to_xml)
+ if file_exists:
+ self.scm.mark_files_updated((path_to_xml,))
+ else:
+ self.scm.add_files((path_to_xml,))
if not self._skip_subdirs['grc']:
ed = CMakeFileEditor(self._file['cmgrc'])
if re.search(fname_xml, ed.cfile) is None and not ed.check_for_glob('*.xml'):
print "Adding GRC bindings to grc/CMakeLists.txt..."
ed.append_value('install', fname_xml, to_ignore_end='DESTINATION[^()]+')
ed.write()
+ self.scm.mark_files_updated(self._file['cmgrc'])
def _parse_cc_h(self, fname_cc):
""" Go through a .cc and .h-file defining a block and return info """
@@ -152,7 +160,7 @@ class ModToolMakeXML(ModTool):
_type_translate
)
except IOError:
- print "Can't open some of the files necessary to parse %s." % fname_cc
- sys.exit(1)
+ raise ModToolException("Can't open some of the files necessary to parse {}.".format(fname_cc))
+
return (parser.read_params(), parser.read_io_signature(), blockname)
diff --git a/gr-utils/python/modtool/modtool_newmod.py b/gr-utils/python/modtool/modtool_newmod.py
index 6e55c5ea59..3e05ecbf48 100644
--- a/gr-utils/python/modtool/modtool_newmod.py
+++ b/gr-utils/python/modtool/modtool_newmod.py
@@ -25,7 +25,8 @@ import os
import re
from optparse import OptionGroup
from gnuradio import gr
-from modtool_base import ModTool
+from modtool_base import ModTool, ModToolException
+from scm import SCMRepoFactory
class ModToolNewModule(ModTool):
""" Create a new out-of-tree module """
@@ -44,17 +45,16 @@ class ModToolNewModule(ModTool):
parser.add_option_group(ogroup)
return parser
- def setup(self):
- (options, self.args) = self.parser.parse_args()
+ def setup(self, options, args):
+ # Don't call ModTool.setup(), that assumes an existing module.
self._info['modname'] = options.module_name
if self._info['modname'] is None:
- if len(self.args) >= 2:
- self._info['modname'] = self.args[1]
+ if len(args) >= 2:
+ self._info['modname'] = args[1]
else:
self._info['modname'] = raw_input('Name of the new module: ')
if not re.match('[a-zA-Z0-9_]+$', self._info['modname']):
- print 'Invalid module name.'
- exit(2)
+ raise ModToolException('Invalid module name.')
self._dir = options.directory
if self._dir == '.':
self._dir = './gr-%s' % self._info['modname']
@@ -63,14 +63,14 @@ class ModToolNewModule(ModTool):
except OSError:
pass # This is what should happen
else:
- print 'The given directory exists.'
- exit(2)
+ raise ModToolException('The given directory exists.')
if options.srcdir is None:
options.srcdir = '/usr/local/share/gnuradio/modtool/gr-newmod'
self._srcdir = gr.prefs().get_string('modtool', 'newmod_path', options.srcdir)
if not os.path.isdir(self._srcdir):
- print 'Error: Could not find gr-newmod source dir.'
- exit(2)
+ raise ModToolException('Could not find gr-newmod source dir.')
+ self.options = options
+ self._setup_scm(mode='new')
def run(self):
"""
@@ -83,9 +83,7 @@ class ModToolNewModule(ModTool):
shutil.copytree(self._srcdir, self._dir)
os.chdir(self._dir)
except OSError:
- print 'Failed.'
- print 'Could not create directory %s. Quitting.' % self._dir
- exit(2)
+ raise ModToolException('Could not create directory %s.' % self._dir)
for root, dirs, files in os.walk('.'):
for filename in files:
f = os.path.join(root, filename)
@@ -98,5 +96,7 @@ class ModToolNewModule(ModTool):
if os.path.basename(root) == 'howto':
os.rename(root, os.path.join(os.path.dirname(root), self._info['modname']))
print "Done."
+ if self.scm.init_repo(path_to_repo="."):
+ print "Created repository... you might want to commit before continuing."
print "Use 'gr_modtool add' to add a new block to this currently empty module."
diff --git a/gr-utils/python/modtool/modtool_rm.py b/gr-utils/python/modtool/modtool_rm.py
index 32dfee4806..47128dbc87 100644
--- a/gr-utils/python/modtool/modtool_rm.py
+++ b/gr-utils/python/modtool/modtool_rm.py
@@ -24,26 +24,27 @@ import os
import re
import sys
import glob
-from optparse import OptionGroup
from util_functions import remove_pattern_from_file
from modtool_base import ModTool
from cmakefile_editor import CMakeFileEditor
+
class ModToolRemove(ModTool):
""" Remove block (delete files and remove Makefile entries) """
name = 'remove'
aliases = ('rm', 'del')
+
def __init__(self):
ModTool.__init__(self)
- def setup(self):
- ModTool.setup(self)
- options = self.options
+ def setup(self, options, args):
+ ModTool.setup(self, options, args)
+
if options.block_name is not None:
self._info['pattern'] = options.block_name
- elif len(self.args) >= 2:
- self._info['pattern'] = self.args[1]
+ elif len(args) >= 2:
+ self._info['pattern'] = args[1]
else:
self._info['pattern'] = raw_input('Which blocks do you want to delete? (Regex): ')
if len(self._info['pattern']) == 0:
@@ -65,16 +66,19 @@ class ModToolRemove(ModTool):
'^\s*s->addTest\(gr::%s::%s::suite\(\)\);\s*$' % (
self._info['modname'], base)
)
+ self.scm.mark_file_updated(self._file['qalib'])
elif ext == '.cc':
ed.remove_value('list',
'\$\{CMAKE_CURRENT_SOURCE_DIR\}/%s' % filename,
to_ignore_start='APPEND test_%s_sources' % self._info['modname'])
+ self.scm.mark_file_updated(ed.filename)
else:
filebase = os.path.splitext(filename)[0]
ed.delete_entry('add_executable', filebase)
ed.delete_entry('target_link_libraries', filebase)
ed.delete_entry('GR_ADD_TEST', filebase)
ed.remove_double_newlines()
+ self.scm.mark_file_updated(ed.filename)
def _remove_py_test_case(filename=None, ed=None):
""" Special function that removes the occurrences of a qa*.{cc,h} file
@@ -102,6 +106,7 @@ class ModToolRemove(ModTool):
for f in incl_files_deleted + swig_files_deleted:
# TODO do this on all *.i files
remove_pattern_from_file(self._file['swig'], _make_swig_regex(f))
+ self.scm.mark_file_updated(self._file['swig'])
if not self._skip_subdirs['python']:
py_files_deleted = self._run_subdir('python', ('*.py',), ('GR_PYTHON_INSTALL',),
cmakeedit_func=_remove_py_test_case)
@@ -111,7 +116,6 @@ class ModToolRemove(ModTool):
if not self._skip_subdirs['grc']:
self._run_subdir('grc', ('*.xml',), ('install',))
-
def _run_subdir(self, path, globs, makefile_vars, cmakeedit_func=None):
""" Delete all files that match a certain pattern in path.
path - The directory in which this will take place
@@ -132,7 +136,7 @@ class ModToolRemove(ModTool):
if len(files_filt) == 0:
print "None found."
return []
- # 2. Delete files, Makefile entries and other occurences
+ # 2. Delete files, Makefile entries and other occurrences
files_deleted = []
ed = CMakeFileEditor('%s/CMakeLists.txt' % path)
yes = self._info['yes']
@@ -148,6 +152,7 @@ class ModToolRemove(ModTool):
continue
files_deleted.append(b)
print "Deleting %s." % f
+ self.scm.remove_file(f)
os.unlink(f)
print "Deleting occurrences of %s from %s/CMakeLists.txt..." % (b, path)
for var in makefile_vars:
@@ -155,5 +160,5 @@ class ModToolRemove(ModTool):
if cmakeedit_func is not None:
cmakeedit_func(b, ed)
ed.write()
+ self.scm.mark_files_updated(('%s/CMakeLists.txt' % path,))
return files_deleted
-
diff --git a/gr-utils/python/modtool/scm.py b/gr-utils/python/modtool/scm.py
new file mode 100644
index 0000000000..ec6023ab3b
--- /dev/null
+++ b/gr-utils/python/modtool/scm.py
@@ -0,0 +1,221 @@
+#
+# Copyright 2013 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+""" Class to handle source code management repositories. """
+
+import subprocess
+
+try:
+ import git
+ HAS_GITPYTHON = True
+except ImportError:
+ HAS_GITPYTHON = False
+# GitPython is a bit too unstable currently
+HAS_GITPYTHON = False
+
+class InvalidSCMError(Exception):
+ """ Exception for when trying to access a repo of wrong type. """
+ def __init__(self):
+ Exception.__init__(self)
+
+### Base class ###############################################################
+class SCMRepository(object):
+ """ Base class to handle interactions with source code management systems. """
+ handles_scm_type = '*'
+ def __init__(self, path_to_repo, is_empty=False):
+ self.path_to_repo = path_to_repo
+ self.is_empty = is_empty
+
+ def init_repo(self, path_to_repo=None, add_files=True):
+ """ Initialize the directory as a repository. Assumes the self.path_to_repo
+ (or path_to_repo, if specified) does *not* contain a valid repository.
+ If add_files is True, all files in this directory are added to version control.
+ Returns true if actually created a repo.
+ """
+ if path_to_repo is not None:
+ self.path_to_repo = path_to_repo
+ return False
+
+ def add_files(self, paths_to_files):
+ """ Add a tuple or list of files to the current repository. """
+ pass
+
+ def add_file(self, path_to_file):
+ """ Add a file to the current repository. """
+ self.add_files([path_to_file])
+
+ def remove_files(self, paths_to_files):
+ """ Remove a tuple or list of files from the current repository. """
+ pass
+
+ def remove_file(self, path_to_file):
+ """ Remove a file from the current repository. """
+ self.remove_files([path_to_file])
+
+ def mark_files_updated(self, paths_to_files):
+ """ Mark a list of tuple of files as changed. """
+ pass
+
+ def mark_file_updated(self, path_to_file):
+ """ Mark a file as changed. """
+ self.mark_files_updated([path_to_file])
+
+ def is_active(self):
+ """ Returns true if this repository manager is operating on an active, source-controlled directory. """
+ return self.is_empty
+
+
+### Git #####################################################################
+class GitManagerGitPython(object):
+ """ Manage git through GitPython (preferred way). """
+ def __init__(self, path_to_repo, init=False):
+ if init:
+ self.repo = git.Repo.init(path_to_repo, mkdir=False)
+ else:
+ try:
+ self.repo = git.Repo(path_to_repo)
+ except git.InvalidGitRepositoryError:
+ self.repo = None
+ raise InvalidSCMError
+ self.index = self.repo.index
+
+ def add_files(self, paths_to_files):
+ """ Adds a tuple of files to the index of the current repository. """
+ if self.repo is not None:
+ self.index.add(paths_to_files)
+
+ def remove_files(self, paths_to_files):
+ """ Removes a tuple of files from the index of the current repository. """
+ if self.repo is not None:
+ self.index.remove(paths_to_files)
+
+
+class GitManagerShell(object):
+ """ Call the git executable through a shell. """
+ def __init__(self, path_to_repo, init=False, git_executable=None):
+ self.path_to_repo = path_to_repo
+ if git_executable is None:
+ try:
+ self.git_executable = subprocess.check_output('which git', shell=True).strip()
+ except (OSError, subprocess.CalledProcessError):
+ raise InvalidSCMError
+ try:
+ if init:
+ subprocess.check_output([self.git_executable, 'init'])
+ else:
+ subprocess.check_output([self.git_executable, 'status'])
+ except OSError:
+ raise InvalidSCMError
+ except subprocess.CalledProcessError:
+ raise InvalidSCMError
+
+ def add_files(self, paths_to_files):
+ """ Adds a tuple of files to the index of the current repository. Does not commit. """
+ subprocess.check_output([self.git_executable, 'add'] + list(paths_to_files))
+
+ def remove_files(self, paths_to_files):
+ """ Removes a tuple of files from the index of the current repository. Does not commit. """
+ subprocess.check_output([self.git_executable, 'rm', '--cached'] + list(paths_to_files))
+
+
+class GitRepository(SCMRepository):
+ """ Specific to operating on git repositories. """
+ handles_scm_type = 'git'
+ def __init__(self, path_to_repo, is_empty=False):
+ SCMRepository.__init__(self, path_to_repo, is_empty)
+ if not is_empty:
+ try:
+ if HAS_GITPYTHON:
+ self.repo_manager = GitManagerGitPython(path_to_repo)
+ else:
+ self.repo_manager = GitManagerShell(path_to_repo)
+ except InvalidSCMError:
+ self.repo_manager = None
+ else:
+ self.repo_manager = None
+
+ def init_repo(self, path_to_repo=None, add_files=True):
+ """ Makes the directory in self.path_to_repo a git repo.
+ If add_file is True, all files in this dir are added to the index. """
+ SCMRepository.init_repo(self, path_to_repo, add_files)
+ if HAS_GITPYTHON:
+ self.repo_manager = GitManagerGitPython(self.path_to_repo, init=True)
+ else:
+ self.repo_manager = GitManagerShell(self.path_to_repo, init=True)
+ if add_files:
+ self.add_files(('*',))
+ return True
+
+ def add_files(self, paths_to_files):
+ """ Add a file to the current repository. Does not commit. """
+ self.repo_manager.add_files(paths_to_files)
+
+ def remove_files(self, paths_to_files):
+ """ Remove a file from the current repository. Does not commit. """
+ self.repo_manager.remove_files(paths_to_files)
+
+ def mark_files_updated(self, paths_to_files):
+ """ Mark a file as changed. Since this is git, same as adding new files. """
+ self.add_files(paths_to_files)
+
+ def is_active(self):
+ return self.repo_manager is not None
+
+
+##############################################################################
+### Factory ##################################################################
+class SCMRepoFactory(object):
+ """ Factory object to create the correct SCM class from the given options and dir. """
+ def __init__(self, options, path_to_repo):
+ self.path_to_repo = path_to_repo
+ self.options = options
+
+ def make_active_scm_manager(self):
+ """ Returns a valid, usable object of type SCMRepository. """
+ if self.options.scm_mode == 'no':
+ return SCMRepository(self.path_to_repo)
+ for glbl in globals().values():
+ try:
+ if issubclass(glbl, SCMRepository):
+ the_scm = glbl(self.path_to_repo)
+ if the_scm.is_active():
+ print 'Found SCM of type:', the_scm.handles_scm_type
+ return the_scm
+ except (TypeError, AttributeError, InvalidSCMError):
+ pass
+ if self.options == 'yes':
+ return None
+ return SCMRepository(self.path_to_repo)
+
+ def make_empty_scm_manager(self, scm_type='git'):
+ """ Returns a valid, usable object of type SCMRepository for an unitialized dir. """
+ if self.options.scm_mode == 'no':
+ return SCMRepository(self.path_to_repo)
+ for glbl in globals().values():
+ try:
+ if issubclass(glbl, SCMRepository):
+ if glbl.handles_scm_type == scm_type:
+ return glbl(self.path_to_repo, is_empty=True)
+ except (TypeError, AttributeError, InvalidSCMError):
+ pass
+ if self.options == 'yes':
+ return None
+ return SCMRepository(self.path_to_repo)
+
diff --git a/gr-utils/python/modtool/util_functions.py b/gr-utils/python/modtool/util_functions.py
index 71a7a7f535..ea7af0cf7c 100644
--- a/gr-utils/python/modtool/util_functions.py
+++ b/gr-utils/python/modtool/util_functions.py
@@ -29,13 +29,8 @@ def get_command_from_argv(possible_cmds):
""" Read the requested command from argv. This can't be done with optparse,
since the option parser isn't defined before the command is known, and
optparse throws an error."""
- command = None
for arg in sys.argv:
- if arg[0] == "-":
- continue
- else:
- command = arg
- if command in possible_cmds:
+ if arg[0] != "-" and arg in possible_cmds:
return arg
return None
@@ -111,7 +106,7 @@ def get_modname():
return None
def is_number(s):
- " Return True if the string s contains a number. "
+ """ Return True if the string s contains a number. """
try:
float(s)
return True
diff --git a/gr-utils/python/utils/gr_modtool b/gr-utils/python/utils/gr_modtool
index 8c5c710aff..e714cf48e5 100755
--- a/gr-utils/python/utils/gr_modtool
+++ b/gr-utils/python/utils/gr_modtool
@@ -21,19 +21,25 @@
#
""" A tool for editing GNU Radio out-of-tree modules. """
-import sys
from gnuradio.modtool import *
+
def main():
""" Here we go. Parse command, choose class and run. """
cmd_dict = get_class_dict(globals().values())
command = get_command_from_argv(cmd_dict.keys())
if command is None:
- print 'Usage:' + templates.Templates['usage']
+ print 'Usage:' + Templates['usage']
exit(2)
modtool = cmd_dict[command]()
- modtool.setup()
- modtool.run()
+ try:
+ (options, args) = modtool.parser.parse_args()
+ modtool.setup(options, args)
+ modtool.run()
+
+ except ModToolException as err:
+ print >> sys.stderr, err
+ exit(1)
if __name__ == '__main__':
try:
diff --git a/gr-video-sdl/python/video_sdl/CMakeLists.txt b/gr-video-sdl/python/video_sdl/CMakeLists.txt
index 2b92efea13..7b2f01aace 100644
--- a/gr-video-sdl/python/video_sdl/CMakeLists.txt
+++ b/gr-video-sdl/python/video_sdl/CMakeLists.txt
@@ -44,6 +44,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-vocoder/python/vocoder/CMakeLists.txt b/gr-vocoder/python/vocoder/CMakeLists.txt
index c776927407..ca8323daab 100644
--- a/gr-vocoder/python/vocoder/CMakeLists.txt
+++ b/gr-vocoder/python/vocoder/CMakeLists.txt
@@ -45,6 +45,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/gr-wavelet/python/wavelet/CMakeLists.txt b/gr-wavelet/python/wavelet/CMakeLists.txt
index 964ef0dab0..bb88c50b65 100644
--- a/gr-wavelet/python/wavelet/CMakeLists.txt
+++ b/gr-wavelet/python/wavelet/CMakeLists.txt
@@ -42,6 +42,6 @@ if(ENABLE_TESTING)
file(GLOB py_qa_test_files "qa_*.py")
foreach(py_qa_test_file ${py_qa_test_files})
get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE)
- GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
+ GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file})
endforeach(py_qa_test_file)
endif(ENABLE_TESTING)
diff --git a/grc/base/FlowGraph.py b/grc/base/FlowGraph.py
index 2f2d8c65e1..c85e3ce233 100644
--- a/grc/base/FlowGraph.py
+++ b/grc/base/FlowGraph.py
@@ -274,6 +274,7 @@ class FlowGraph(Element):
if block: block.import_data(block_n)
else: Messages.send_error_load('Block key "%s" not found in %s'%(key, self.get_parent()))
#build the connections
+ block_ids = map(lambda b: b.get_id(), self.get_blocks())
for connection_n in connections_n:
#try to make the connection
try:
@@ -284,7 +285,6 @@ class FlowGraph(Element):
source_key = connection_n.find('source_key')
sink_key = connection_n.find('sink_key')
#verify the blocks
- block_ids = map(lambda b: b.get_id(), self.get_blocks())
if source_block_id not in block_ids:
raise LookupError('source block id "%s" not in block ids'%source_block_id)
if sink_block_id not in block_ids:
@@ -292,6 +292,9 @@ class FlowGraph(Element):
#get the blocks
source_block = self.get_block(source_block_id)
sink_block = self.get_block(sink_block_id)
+ # update numeric message ports keys
+ source_key = self.update_message_port_key(source_key, source_block.get_sources())
+ sink_key = self.update_message_port_key(sink_key, sink_block.get_sinks())
#verify the ports
if source_key not in source_block.get_source_keys():
raise LookupError('source key "%s" not in source block keys'%source_key)
@@ -308,3 +311,23 @@ class FlowGraph(Element):
)
)
self.rewrite() #global rewrite
+
+
+ def update_message_port_key(self, key, ports):
+ """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).
+
+ :param key: the port key to be updated
+ :param ports: list of candidate ports
+ :returns: the updated key or the original one
+ """
+ if key.isdigit(): # don't bother current message port keys
+ port = ports[int(key)] # get port (assuming liner indexed keys)
+ if port.get_type() == "message":
+ return port.get_key() # for message ports get updated key
+ return key # do nothing \ No newline at end of file
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 87576ccae1..a891298fa4 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -113,7 +113,8 @@ class ActionHandler:
Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS,
Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY,
Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY,
- Actions.TYPES_WINDOW_DISPLAY,
+ Actions.TYPES_WINDOW_DISPLAY, Actions.TOGGLE_BLOCKS_WINDOW,
+ Actions.TOGGLE_REPORTS_WINDOW,
): action.set_sensitive(True)
if not self.init_file_paths:
self.init_file_paths = Preferences.files_open()
@@ -125,6 +126,8 @@ class ActionHandler:
if not self.get_page(): self.main_window.new_page() #ensure that at least a blank page exists
self.main_window.btwin.search_entry.hide()
+ Actions.TOGGLE_REPORTS_WINDOW.set_active(Preferences.reports_window_visibility())
+ Actions.TOGGLE_BLOCKS_WINDOW.set_active(Preferences.blocks_window_visibility())
elif action == Actions.APPLICATION_QUIT:
if self.main_window.close_pages():
gtk.main_quit()
@@ -349,6 +352,14 @@ class ActionHandler:
Dialogs.TypesDialog(self.get_flow_graph().get_parent())
elif action == Actions.ERRORS_WINDOW_DISPLAY:
Dialogs.ErrorsDialog(self.get_flow_graph())
+ elif action == Actions.TOGGLE_REPORTS_WINDOW:
+ visible = action.get_active()
+ self.main_window.reports_scrolled_window.set_visible(visible)
+ Preferences.reports_window_visibility(visible)
+ elif action == Actions.TOGGLE_BLOCKS_WINDOW:
+ visible = action.get_active()
+ self.main_window.btwin.set_visible(visible)
+ Preferences.blocks_window_visibility(visible)
##################################################
# Param Modifications
##################################################
@@ -447,6 +458,7 @@ class ActionHandler:
self.main_window.btwin.clear();
self.platform.load_block_tree(self.main_window.btwin);
elif action == Actions.FIND_BLOCKS:
+ self.main_window.btwin.show()
self.main_window.btwin.search_entry.show()
self.main_window.set_focus(self.main_window.btwin.search_entry)
elif action == Actions.OPEN_HIER:
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index 17b7df6e6a..e96fb4d276 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -57,27 +57,13 @@ def get_all_actions(): return _all_actions_list
_accel_group = gtk.AccelGroup()
def get_accel_group(): return _accel_group
-class Action(gtk.Action):
+
+class _ActionBase(object):
"""
- A custom Action class based on gtk.Action.
- Pass additional arguments such as keypresses.
+ Base class for Action and ToggleAction
Register actions and keypresses with this module.
"""
-
- def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None):
- """
- Create a new Action instance.
-
- Args:
- key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...)
- the: regular gtk.Action parameters (defaults to None)
- """
- if name is None: name = label
- gtk.Action.__init__(self,
- name=name, label=label,
- tooltip=tooltip, stock_id=stock_id,
- )
- #register this action
+ def __init__(self, label, keypresses):
_all_actions_list.append(self)
for i in range(len(keypresses)/2):
keyval, mod_mask = keypresses[i*2:(i+1)*2]
@@ -111,6 +97,52 @@ class Action(gtk.Action):
"""
self.emit('activate')
+
+class Action(gtk.Action, _ActionBase):
+ """
+ A custom Action class based on gtk.Action.
+ Pass additional arguments such as keypresses.
+ """
+
+ def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None):
+ """
+ Create a new Action instance.
+
+ Args:
+ key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...)
+ the: regular gtk.Action parameters (defaults to None)
+ """
+ if name is None: name = label
+ gtk.Action.__init__(self,
+ name=name, label=label,
+ tooltip=tooltip, stock_id=stock_id,
+ )
+ #register this action
+ _ActionBase.__init__(self, label, keypresses)
+
+
+class ToggleAction(gtk.ToggleAction, _ActionBase):
+ """
+ A custom Action class based on gtk.ToggleAction.
+ Pass additional arguments such as keypresses.
+ """
+
+ def __init__(self, keypresses=(), name=None, label=None, tooltip=None, stock_id=None):
+ """
+ Create a new ToggleAction instance.
+
+ Args:
+ key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...)
+ the: regular gtk.Action parameters (defaults to None)
+ """
+ if name is None: name = label
+ gtk.ToggleAction.__init__(self,
+ name=name, label=label,
+ tooltip=tooltip, stock_id=stock_id,
+ )
+ #register this action
+ _ActionBase.__init__(self, label, keypresses)
+
########################################################################
# Actions
########################################################################
@@ -233,6 +265,16 @@ ERRORS_WINDOW_DISPLAY = Action(
tooltip='View flow graph errors',
stock_id=gtk.STOCK_DIALOG_ERROR,
)
+TOGGLE_REPORTS_WINDOW = ToggleAction(
+ label='Show _Reports',
+ tooltip='Toggle visibility of the Report widget',
+ keypresses=(gtk.keysyms.r, gtk.gdk.CONTROL_MASK),
+)
+TOGGLE_BLOCKS_WINDOW = ToggleAction(
+ label='Show _Block Tree',
+ tooltip='Toggle visibility of the block tree widget',
+ keypresses=(gtk.keysyms.b, gtk.gdk.CONTROL_MASK),
+)
ABOUT_WINDOW_DISPLAY = Action(
label='_About',
tooltip='About this program',
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index 92d87c8809..0e2b29c4e3 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -57,6 +57,7 @@ TOOLBAR_LIST = (
)
##The list of actions and categories for the menu bar.
+
MENU_BAR_LIST = (
(gtk.Action('File', '_File', None, None), [
Actions.FLOW_GRAPH_NEW,
@@ -88,6 +89,9 @@ MENU_BAR_LIST = (
Actions.BLOCK_PARAM_MODIFY,
]),
(gtk.Action('View', '_View', None, None), [
+ Actions.TOGGLE_BLOCKS_WINDOW,
+ Actions.TOGGLE_REPORTS_WINDOW,
+ None,
Actions.ERRORS_WINDOW_DISPLAY,
Actions.FIND_BLOCKS,
]),
@@ -103,7 +107,6 @@ MENU_BAR_LIST = (
Actions.ABOUT_WINDOW_DISPLAY,
]),
)
-
class Toolbar(gtk.Toolbar):
"""The gtk toolbar with actions added from the toolbar list."""
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
index 9ea37c55e0..b04a4dda7c 100644
--- a/grc/gui/BlockTreeWindow.py
+++ b/grc/gui/BlockTreeWindow.py
@@ -226,6 +226,10 @@ class BlockTreeWindow(gtk.VBox):
# manually trigger action...
Actions.FIND_BLOCKS.activate()
+ elif event.state & gtk.gdk.CONTROL_MASK and event.keyval == gtk.keysyms.b:
+ # ugly...
+ Actions.TOGGLE_BLOCKS_WINDOW.activate()
+
else:
return False # propagate event
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index 0f631791db..3410e3a93b 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -21,6 +21,7 @@ import Utils
from Element import Element
import Colors
from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT
+import gtk
class Connection(Element):
"""
@@ -150,7 +151,11 @@ class Connection(Element):
if self.is_highlighted(): border_color = Colors.HIGHLIGHT_COLOR
elif self.get_enabled(): border_color = Colors.CONNECTION_ENABLED_COLOR
else: border_color = Colors.CONNECTION_DISABLED_COLOR
+ # make message connections dashed (no areas here)
+ normal_line_style = gc.line_style
+ if source.get_type() == "message": gc.line_style = gtk.gdk.LINE_ON_OFF_DASH
Element.draw(self, gc, window, bg_color=None, border_color=border_color)
+ gc.line_style = normal_line_style # restore line style
#draw arrow on sink port
try:
gc.set_foreground(self._arrow_color)
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
index 14139691d2..5f2044aa64 100644
--- a/grc/gui/MainWindow.py
+++ b/grc/gui/MainWindow.py
@@ -109,6 +109,8 @@ class MainWindow(gtk.Window):
self.flow_graph_vpaned.set_position(Preferences.reports_window_position())
self.hpaned.set_position(Preferences.blocks_window_position())
self.show_all()
+ self.reports_scrolled_window.hide()
+ self.btwin.hide()
############################################################
# Event Handlers
diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py
index ce545cab6a..c315436cae 100644
--- a/grc/gui/Preferences.py
+++ b/grc/gui/Preferences.py
@@ -84,3 +84,15 @@ def blocks_window_position(pos=None):
else:
try: return _config_parser.getint('main', 'blocks_window_position') or 1 #greater than 0
except: return -1
+
+def reports_window_visibility(visible=None):
+ if visible is not None: _config_parser.set('main', 'reports_window_visible', visible)
+ else:
+ try: return _config_parser.getboolean('main', 'reports_window_visible')
+ except: return True
+
+def blocks_window_visibility(visible=None):
+ if visible is not None: _config_parser.set('main', 'blocks_window_visible', visible)
+ else:
+ try: return _config_parser.getboolean('main', 'blocks_window_visible')
+ except: return True
diff --git a/grc/python/Block.py b/grc/python/Block.py
index e13b26c12f..5dffcb3124 100644
--- a/grc/python/Block.py
+++ b/grc/python/Block.py
@@ -97,54 +97,29 @@ class Block(_Block, _GUIBlock):
"""
_Block.rewrite(self)
- def rectify(ports):
- #restore integer contiguity after insertion
- #rectify the port names with the index
- self.back_ofthe_bus(ports);
- for i, port in enumerate(ports):
- port._key = str(i)
- port._name = port._n['name']
- if len(ports) > 1 and not port._type == 'bus': port._name += str(i)
-
- def insert_port(get_ports, get_port, key):
- prev_port = get_port(str(int(key)-1))
- get_ports().insert(
- get_ports().index(prev_port)+1,
- prev_port.copy(new_key=key),
- )
- rectify(get_ports())
-
- def remove_port(get_ports, get_port, key):
- port = get_port(key)
- for connection in port.get_connections():
- self.get_parent().remove_element(connection)
- get_ports().remove(port)
- rectify(get_ports())
-
- #adjust nports
- for get_ports, get_port in (
- (self.get_sources, self.get_source),
- (self.get_sinks, self.get_sink),
- ):
- master_ports = filter(lambda p: p.get_nports(), get_ports())
- for i, master_port in enumerate(master_ports):
- nports = master_port.get_nports()
- index_first = get_ports().index(master_port)
- try: index_last = get_ports().index(master_ports[i+1])
- except IndexError: index_last = len(get_ports())
- num_ports = index_last - index_first
- #do nothing if nports is already num ports
- if nports == num_ports: continue
- #remove excess ports and connections
- if nports < num_ports:
- for key in reversed(map(str, range(index_first+nports, index_first+num_ports))):
- remove_port(get_ports, get_port, key);
- continue
- #add more ports
- if nports > num_ports:
- for key in map(str, range(index_first+num_ports, index_first+nports)):
- insert_port(get_ports, get_port, key)
+ # adjust nports
+ 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 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 i in range(num_ports, nports):
+ port = master_port.add_clone()
+ ports.insert(ports.index(master_port) + i, port)
+
+ self.back_ofthe_bus(ports)
+ # renumber non-message/-msg ports
+ for i, port in enumerate(filter(lambda p: p.get_key().isdigit(), ports)):
+ port._key = str(i)
def port_controller_modify(self, direction):
"""
diff --git a/grc/python/Port.py b/grc/python/Port.py
index 247dbed3e6..b82995cf6f 100644
--- a/grc/python/Port.py
+++ b/grc/python/Port.py
@@ -110,6 +110,7 @@ class Port(_Port, _GUIPort):
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()
@@ -178,18 +179,18 @@ class Port(_Port, _GUIPort):
"""
Get the number of ports.
If already blank, return a blank
- If the evaluation of nports cannot be cast to an integer, return 1.
+ 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)
- #return blank if nports is blank
- if not nports: return ''
try:
- nports = int(self.get_parent().get_parent().evaluate(nports))
- if 0 < nports: return nports
- except: return 1
+ return max(1, int(self.get_parent().get_parent().evaluate(nports)))
+ except:
+ return 1
def get_optional(self): return bool(self._optional)
@@ -216,9 +217,49 @@ class Port(_Port, _GUIPort):
return '#%.2x%.2x%.2x'%(r, g, b)
except: return _Port.get_color(self)
- def copy(self, new_key=None):
+ 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()
- #remove nports from the key so the copy cannot be a duplicator
- if n.has_key('nports'): n.pop('nports')
- if new_key: n['key'] = new_key
- return self.__class__(self.get_parent(), n, self._dir)
+ 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/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl
index cf13317d1d..c18245e819 100644
--- a/grc/python/flow_graph.tmpl
+++ b/grc/python/flow_graph.tmpl
@@ -216,7 +216,7 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))])
#for $msg in $messages2
#set $sr = $msg.get_source()
#set $source = "self.%s"%($sr.get_parent().get_id())
- #set $source_port = $sr.get_name();
+ #set $source_port = $sr.get_key();
#if $sr.get_parent().get_key() == "pad_source"
#set $source = "self"
#set $source_port = $sr.get_parent().get_param("label").get_value();
diff --git a/volk/apps/CMakeLists.txt b/volk/apps/CMakeLists.txt
index f847dd6245..e3d25f07e2 100644
--- a/volk/apps/CMakeLists.txt
+++ b/volk/apps/CMakeLists.txt
@@ -30,9 +30,11 @@ include_directories(
${CMAKE_SOURCE_DIR}/include
${CMAKE_BINARY_DIR}/include
${CMAKE_SOURCE_DIR}/lib
+ ${CMAKE_BINARY_DIR}/lib
${Boost_INCLUDE_DIRS}
)
+# MAKE volk_profile
add_executable(volk_profile
${CMAKE_CURRENT_SOURCE_DIR}/volk_profile.cc
${CMAKE_SOURCE_DIR}/lib/qa_utils.cc
@@ -46,4 +48,14 @@ install(
COMPONENT "volk"
)
+# MAKE volk-config-info
+add_executable(volk-config-info volk-config-info.cc)
+target_link_libraries(volk-config-info volk ${Boost_LIBRARIES})
+
+install(
+ TARGETS volk-config-info
+ DESTINATION bin
+ COMPONENT "volk"
+)
+
endif(Boost_FOUND)
diff --git a/volk/apps/volk-config-info.cc b/volk/apps/volk-config-info.cc
new file mode 100644
index 0000000000..11011d2d00
--- /dev/null
+++ b/volk/apps/volk-config-info.cc
@@ -0,0 +1,96 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <volk/constants.h>
+#include "volk/volk.h"
+#include <boost/program_options.hpp>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+int
+main(int argc, char **argv)
+{
+ po::options_description desc("Program options: volk-config-info [options]");
+ po::variables_map vm;
+
+ desc.add_options()
+ ("help,h", "print help message")
+ ("prefix", "print VOLK installation prefix")
+ ("builddate", "print VOLK build date (RFC2822 format)")
+ ("cc", "print VOLK C compiler version")
+ ("cflags", "print VOLK CFLAGS")
+ ("all-machines", "print VOLK machines built into library")
+ ("avail-machines", "print VOLK machines the current platform can use")
+ ("machine", "print the VOLK machine that will be used")
+ ("version,v", "print VOLK version")
+ ;
+
+ try {
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+ }
+ catch (po::error& error){
+ std::cerr << "Error: " << error.what() << std::endl << std::endl;
+ std::cerr << desc << std::endl;
+ return 1;
+ }
+
+ if(vm.size() == 0 || vm.count("help")) {
+ std::cout << desc << std::endl;
+ return 1;
+ }
+
+ if(vm.count("prefix"))
+ std::cout << volk_prefix() << std::endl;
+
+ if(vm.count("builddate"))
+ std::cout << volk_build_date() << std::endl;
+
+ if(vm.count("version"))
+ std::cout << volk_version() << std::endl;
+
+ if(vm.count("cc"))
+ std::cout << volk_c_compiler() << std::endl;
+
+ if(vm.count("cflags"))
+ std::cout << volk_compiler_flags() << std::endl;
+
+ // stick an extra ';' to make output of this and avail-machines the
+ // same structure for easier parsing
+ if(vm.count("all-machines"))
+ std::cout << volk_available_machines() << ";" << std::endl;
+
+ if(vm.count("avail-machines")) {
+ volk_list_machines();
+ }
+
+ if(vm.count("machine")) {
+ std::cout << volk_get_machine() << std::endl;
+ }
+
+ return 0;
+}
diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc
index 3de6f23884..c668b3fa37 100644
--- a/volk/apps/volk_profile.cc
+++ b/volk/apps/volk_profile.cc
@@ -7,6 +7,7 @@
#include <vector>
#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
+#include <boost/program_options.hpp>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
@@ -15,97 +16,122 @@
namespace fs = boost::filesystem;
int main(int argc, char *argv[]) {
+ boost::program_options::options_description desc("Options");
+ desc.add_options()
+ ("help,h", "Print help messages")
+ ("benchmark,b", boost::program_options::value<bool>()->default_value( false ), "run all kernels (benchmark mode)");
+ //("benchmark,b", boost::program_options::value<bool>(&benchmark_mode)->default_value( false ), "run all kernels (benchmark mode)");
+ boost::program_options::variables_map vm;
+ bool benchmark_mode = false;
+ try {
+ boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
+ boost::program_options::notify(vm);
+ benchmark_mode = vm.count("benchmark")?vm["benchmark"].as<bool>():false;
+ } catch (boost::program_options::error& error) {
+ std::cerr << "Error: " << error.what() << std::endl << std::endl;
+ std::cerr << desc << std::endl;
+ return 1;
+ }
+ /** --help option
+ */
+ if ( vm.count("help") )
+ {
+ std::cout << "Basic Command Line Parameter App" << std::endl
+ << desc << std::endl;
+ return 0;
+ }
+
std::vector<std::string> results;
- //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4, 1e-4, 2046, 10000, &results);
- //VOLK_PROFILE(volk_16i_branch_4_state_8, 1e-4, 2046, 10000, &results);
- VOLK_PUPPET_PROFILE(volk_32fc_s32fc_rotatorpuppet_32fc, volk_32fc_s32fc_x2_rotator_32fc, 1e-2, (lv_32fc_t)lv_cmake(.95393, .3), 20462, 10000, &results);
- VOLK_PROFILE(volk_16ic_s32f_deinterleave_real_32f, 1e-5, 32768.0, 204602, 10000, &results);
- VOLK_PROFILE(volk_16ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_16ic_deinterleave_16i_x2, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_16ic_s32f_deinterleave_32f_x2, 1e-4, 32768.0, 204602, 1000, &results);
- VOLK_PROFILE(volk_16ic_deinterleave_real_16i, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_16ic_magnitude_16i, 1, 0, 204602, 100, &results);
- VOLK_PROFILE(volk_16ic_s32f_magnitude_32f, 1e-5, 32768.0, 204602, 1000, &results);
- VOLK_PROFILE(volk_16i_s32f_convert_32f, 1e-4, 32768.0, 204602, 10000, &results);
- VOLK_PROFILE(volk_16i_convert_8i, 0, 0, 204602, 10000, &results);
- //VOLK_PROFILE(volk_16i_max_star_16i, 0, 0, 204602, 10000, &results);
- //VOLK_PROFILE(volk_16i_max_star_horizontal_16i, 0, 0, 204602, 10000, &results);
- //VOLK_PROFILE(volk_16i_permute_and_scalar_add, 1e-4, 0, 2046, 10000, &results);
- //VOLK_PROFILE(volk_16i_x4_quad_max_star_16i, 1e-4, 0, 2046, 10000, &results);
- VOLK_PROFILE(volk_16u_byteswap, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_accumulator_s32f, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_x2_add_32f, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_32f_multiply_32fc, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_s32f_power_32fc, 1e-4, 0, 204602, 50, &results);
- VOLK_PROFILE(volk_32f_s32f_calc_spectral_noise_floor_32f, 1e-4, 20.0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_s32f_atan2_32f, 1e-4, 10.0, 204602, 100, &results);
- //VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 2046, 10000, &results);
- VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_deinterleave_32f_x2, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_deinterleave_64f_x2, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_s32f_deinterleave_real_16i, 0, 32768, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_deinterleave_imag_32f, 1e-4, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32fc_deinterleave_real_32f, 1e-4, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32fc_deinterleave_real_64f, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_x2_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_32f_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_index_max_16u, 3, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_s32f_magnitude_16i, 1, 32768, 204602, 100, &results);
- VOLK_PROFILE(volk_32fc_magnitude_32f, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_magnitude_squared_32f, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_x2_multiply_32fc, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_x2_multiply_conjugate_32fc, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_conjugate_32fc, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32f_s32f_convert_16i, 1, 32768, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_s32f_convert_32i, 1, 2<<31, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_convert_64f, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_s32f_convert_8i, 1, 128, 204602, 10000, &results);
- //VOLK_PROFILE(volk_32fc_s32f_x2_power_spectral_density_32f, 1e-4, 2046, 10000, &results);
- VOLK_PROFILE(volk_32fc_s32f_power_spectrum_32f, 1e-4, 0, 20462, 100, &results);
- VOLK_PROFILE(volk_32fc_x2_square_dist_32f, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32fc_x2_s32f_square_dist_scalar_mult_32f, 1e-4, 10, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_x2_divide_32f, 1e-4, 0, 204602, 2000, &results);
- VOLK_PROFILE(volk_32f_x2_dot_prod_32f, 1e-4, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32f_x2_dot_prod_16i, 1e-4, 0, 204602, 5000, &results);
- //VOLK_PROFILE(volk_32f_s32f_32f_fm_detect_32f, 1e-4, 2046, 10000, &results);
- VOLK_PROFILE(volk_32f_index_max_16u, 3, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32f_x2_s32f_interleave_16ic, 1, 32768, 204602, 3000, &results);
- VOLK_PROFILE(volk_32f_x2_interleave_32fc, 0, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32f_x2_max_32f, 1e-4, 0, 204602, 2000, &results);
- VOLK_PROFILE(volk_32f_x2_min_32f, 1e-4, 0, 204602, 2000, &results);
- VOLK_PROFILE(volk_32f_x2_multiply_32f, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_s32f_normalize, 1e-4, 100, 204602, 10000, &results);
- VOLK_PROFILE(volk_32f_s32f_power_32f, 1e-4, 4, 204602, 100, &results);
- VOLK_PROFILE(volk_32f_sqrt_32f, 1e-4, 0, 204602, 100, &results);
- VOLK_PROFILE(volk_32f_s32f_stddev_32f, 1e-4, 100, 204602, 3000, &results);
- VOLK_PROFILE(volk_32f_stddev_and_mean_32f_x2, 1e-4, 0, 204602, 3000, &results);
- VOLK_PROFILE(volk_32f_x2_subtract_32f, 1e-4, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32f_x3_sum_of_poly_32f, 1e-4, 0, 204602, 5000, &results);
- VOLK_PROFILE(volk_32i_x2_and_32i, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32i_s32f_convert_32f, 1e-4, 100, 204602, 10000, &results);
- VOLK_PROFILE(volk_32i_x2_or_32i, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_32u_byteswap, 0, 0, 204602, 2000, &results);
- //VOLK_PROFILE(volk_32u_popcnt, 0, 0, 2046, 10000, &results);
- VOLK_PROFILE(volk_64f_convert_32f, 1e-4, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_64f_x2_max_64f, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_64f_x2_min_64f, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_64u_byteswap, 0, 0, 204602, 1000, &results);
- //VOLK_PROFILE(volk_64u_popcnt, 0, 0, 2046, 10000, &results);
- VOLK_PROFILE(volk_8ic_deinterleave_16i_x2, 0, 0, 204602, 3000, &results);
- VOLK_PROFILE(volk_8ic_s32f_deinterleave_32f_x2, 1e-4, 100, 204602, 3000, &results);
- VOLK_PROFILE(volk_8ic_deinterleave_real_16i, 0, 256, 204602, 3000, &results);
- VOLK_PROFILE(volk_8ic_s32f_deinterleave_real_32f, 1e-4, 100, 204602, 3000, &results);
- VOLK_PROFILE(volk_8ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results);
- VOLK_PROFILE(volk_8ic_x2_multiply_conjugate_16ic, 0, 0, 204602, 400, &results);
- VOLK_PROFILE(volk_8ic_x2_s32f_multiply_conjugate_32fc, 1e-4, 100, 204602, 400, &results);
- VOLK_PROFILE(volk_8i_convert_16i, 0, 0, 204602, 20000, &results);
- VOLK_PROFILE(volk_8i_s32f_convert_32f, 1e-4, 100, 204602, 2000, &results);
- //VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, lv_32fc_t(1.0, 0.5), 204602, 1000, &results);
- VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, 0, 204602, 1000, &results);
- VOLK_PROFILE(volk_32f_s32f_multiply_32f, 1e-4, 1.0, 204602, 10000, &results);
+ //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4, 1e-4, 2046, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_16i_branch_4_state_8, 1e-4, 2046, 10000, &results, benchmark_mode);
+ VOLK_PUPPET_PROFILE(volk_32fc_s32fc_rotatorpuppet_32fc, volk_32fc_s32fc_x2_rotator_32fc, 1e-2, (lv_32fc_t)lv_cmake(.95393, .3), 20462, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_s32f_deinterleave_real_32f, 1e-5, 32768.0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_deinterleave_16i_x2, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_s32f_deinterleave_32f_x2, 1e-4, 32768.0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_deinterleave_real_16i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_magnitude_16i, 1, 0, 204602, 100, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16ic_s32f_magnitude_32f, 1e-5, 32768.0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16i_s32f_convert_32f, 1e-4, 32768.0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16i_convert_8i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_16i_max_star_16i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_16i_max_star_horizontal_16i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_16i_permute_and_scalar_add, 1e-4, 0, 2046, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_16i_x4_quad_max_star_16i, 1e-4, 0, 2046, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16u_byteswap, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_accumulator_s32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_add_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_32f_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_s32f_power_32fc, 1e-4, 0, 204602, 50, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_calc_spectral_noise_floor_32f, 1e-4, 20.0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_s32f_atan2_32f, 1e-4, 10.0, 204602, 100, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 2046, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_x2_conjugate_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_deinterleave_32f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_deinterleave_64f_x2, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_s32f_deinterleave_real_16i, 0, 32768, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_deinterleave_imag_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_deinterleave_real_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_deinterleave_real_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_x2_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_32f_dot_prod_32fc, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_index_max_16u, 3, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_s32f_magnitude_16i, 1, 32768, 204602, 100, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_magnitude_32f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_magnitude_squared_32f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_x2_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_x2_multiply_conjugate_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_conjugate_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_convert_16i, 1, 32768, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_convert_32i, 1, 2<<31, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_convert_64f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_convert_8i, 1, 128, 204602, 10000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_32fc_s32f_x2_power_spectral_density_32f, 1e-4, 2046, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_s32f_power_spectrum_32f, 1e-4, 0, 20462, 100, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_x2_square_dist_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_x2_s32f_square_dist_scalar_mult_32f, 1e-4, 10, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_divide_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_dot_prod_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_dot_prod_16i, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_32f_s32f_32f_fm_detect_32f, 1e-4, 2046, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_index_max_16u, 3, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_s32f_interleave_16ic, 1, 32768, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_interleave_32fc, 0, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_max_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_min_32f, 1e-4, 0, 204602, 2000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_multiply_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_normalize, 1e-4, 100, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_power_32f, 1e-4, 4, 204602, 100, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_sqrt_32f, 1e-4, 0, 204602, 100, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_stddev_32f, 1e-4, 100, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_stddev_and_mean_32f_x2, 1e-4, 0, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x2_subtract_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_x3_sum_of_poly_32f, 1e-4, 0, 204602, 5000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32i_x2_and_32i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32i_s32f_convert_32f, 1e-4, 100, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32i_x2_or_32i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32u_byteswap, 0, 0, 204602, 2000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_32u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_64f_convert_32f, 1e-4, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_64f_x2_max_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_64f_x2_min_64f, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_64u_byteswap, 0, 0, 204602, 1000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_64u_popcnt, 0, 0, 2046, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_deinterleave_16i_x2, 0, 0, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_s32f_deinterleave_32f_x2, 1e-4, 100, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_deinterleave_real_16i, 0, 256, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_s32f_deinterleave_real_32f, 1e-4, 100, 204602, 3000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_deinterleave_real_8i, 0, 0, 204602, 10000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_x2_multiply_conjugate_16ic, 0, 0, 204602, 400, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8ic_x2_s32f_multiply_conjugate_32fc, 1e-4, 100, 204602, 400, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8i_convert_16i, 0, 0, 204602, 20000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_8i_s32f_convert_32f, 1e-4, 100, 204602, 2000, &results, benchmark_mode);
+ //VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, lv_32fc_t(1.0, 0.5), 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32fc_s32fc_multiply_32fc, 1e-4, 0, 204602, 1000, &results, benchmark_mode);
+ VOLK_PROFILE(volk_32f_s32f_multiply_32f, 1e-4, 1.0, 204602, 10000, &results, benchmark_mode);
char path[1024];
diff --git a/volk/cmake/GrBoost.cmake b/volk/cmake/GrBoost.cmake
index 57db9db379..8b0f07f702 100644
--- a/volk/cmake/GrBoost.cmake
+++ b/volk/cmake/GrBoost.cmake
@@ -30,6 +30,7 @@ set(BOOST_REQUIRED_COMPONENTS
filesystem
system
unit_test_framework
+ program_options
)
if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
diff --git a/volk/gen/archs.xml b/volk/gen/archs.xml
index 9cb9b8d017..647598832e 100644
--- a/volk/gen/archs.xml
+++ b/volk/gen/archs.xml
@@ -10,9 +10,16 @@
<check name="has_ppc"></check>
</arch>
+<arch name="softfp">
+ <flag compiler="gnu">-mfloat-abi=softfp</flag>
+</arch>
+
+<arch name="hardfp">
+ <flag compiler="gnu">-mfloat-abi=hard</flag>
+</arch>
+
<arch name="neon">
<flag compiler="gnu">-mfpu=neon</flag>
- <flag compiler="gnu">-mfloat-abi=softfp</flag>
<flag compiler="gnu">-funsafe-math-optimizations</flag>
<alignment>16</alignment>
<check name="has_neon"></check>
diff --git a/volk/gen/machines.xml b/volk/gen/machines.xml
index d88a1a50cc..357bf75194 100644
--- a/volk/gen/machines.xml
+++ b/volk/gen/machines.xml
@@ -15,7 +15,7 @@
-->
<machine name="neon">
-<archs>generic neon orc|</archs>
+<archs>generic neon softfp|hardfp orc|</archs>
</machine>
<!-- trailing | bar means generate without either for MSVC -->
diff --git a/volk/include/volk/constants.h b/volk/include/volk/constants.h
new file mode 100644
index 0000000000..bac0e36c5e
--- /dev/null
+++ b/volk/include/volk/constants.h
@@ -0,0 +1,39 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2009,2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_VOLK_CONSTANTS_H
+#define INCLUDED_VOLK_CONSTANTS_H
+
+#include <volk/volk_common.h>
+
+__VOLK_DECL_BEGIN
+
+VOLK_API char* volk_prefix();
+VOLK_API char* volk_build_date();
+VOLK_API char* volk_version();
+VOLK_API char* volk_c_compiler();
+VOLK_API char* volk_compiler_flags();
+VOLK_API char* volk_available_machines();
+
+__VOLK_DECL_END
+
+#endif /* INCLUDED_VOLK_CONSTANTS_H */
diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt
index 4ac67bcb69..07e1408b51 100644
--- a/volk/lib/CMakeLists.txt
+++ b/volk/lib/CMakeLists.txt
@@ -271,6 +271,14 @@ gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_config_fixed.tmpl.h ${CMAKE_BINARY_DI
gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machines.tmpl.h ${CMAKE_BINARY_DIR}/lib/volk_machines.h)
gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machines.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk_machines.c)
+set(BASE_CFLAGS NONE)
+STRING(TOUPPER ${CMAKE_BUILD_TYPE} CBTU)
+MESSAGE(STATUS BUILT TYPE ${CBTU})
+MESSAGE(STATUS "Base cflags = ${CMAKE_C_FLAGS_${CBTU}} ${CMAKE_C_FLAGS}")
+set(COMPILER_INFO "")
+execute_process(COMMAND ${CMAKE_C_COMPILER} --version
+ OUTPUT_VARIABLE cmake_c_compiler_version)
+
foreach(machine_name ${available_machines})
#generate machine source
set(machine_source ${CMAKE_CURRENT_BINARY_DIR}/volk_machine_${machine_name}.c)
@@ -283,6 +291,8 @@ foreach(machine_name ${available_machines})
--mode "machine_flags" --machine "${machine_name}" --compiler "${COMPILER_NAME}"
OUTPUT_VARIABLE ${machine_name}_flags OUTPUT_STRIP_TRAILING_WHITESPACE
)
+ MESSAGE(STATUS "BUILD INFO ::: ${machine_name} ::: ${COMPILER_NAME} ::: ${CMAKE_C_FLAGS_${CBTU}} ${CMAKE_C_FLAGS} ${${machine_name}_flags}")
+ set(COMPILER_INFO "${COMPILER_INFO}${machine_name}:::${COMPILER_NAME}:::${CMAKE_C_FLAGS_${CBTU}} ${CMAKE_C_FLAGS} ${${machine_name}_flags}\n" )
if(${machine_name}_flags)
set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS "${${machine_name}_flags}")
endif()
@@ -292,6 +302,13 @@ foreach(machine_name ${available_machines})
list(APPEND machine_defs ${machine_def})
endforeach(machine_name)
+# Convert to a C string to compile and display properly
+string(STRIP "${cmake_c_compiler_version}" cmake_c_compiler_version)
+string(STRIP ${COMPILER_INFO} COMPILER_INFO)
+MESSAGE(STATUS "Compiler Version: ${cmake_c_compiler_version}")
+string(REPLACE "\n" " \\n" cmake_c_compiler_version ${cmake_c_compiler_version})
+string(REPLACE "\n" " \\n" COMPILER_INFO ${COMPILER_INFO})
+
########################################################################
# Set local include directories first
########################################################################
@@ -332,6 +349,28 @@ else()
message(STATUS "Did not find liborc and orcc, disabling orc support...")
endif()
+
+########################################################################
+# Handle the generated constants
+########################################################################
+
+execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
+ "import time;print time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())"
+ OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+message(STATUS "Loading build date ${BUILD_DATE} into constants...")
+message(STATUS "Loading version ${VERSION} into constants...")
+
+#double escape for windows backslash path separators
+string(REPLACE "\\" "\\\\" prefix ${prefix})
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/constants.c.in
+ ${CMAKE_CURRENT_BINARY_DIR}/constants.c
+@ONLY)
+
+list(APPEND volk_sources ${CMAKE_CURRENT_BINARY_DIR}/constants.c)
+
########################################################################
# Setup the volk sources list and library
########################################################################
diff --git a/volk/lib/constants.c.in b/volk/lib/constants.c.in
new file mode 100644
index 0000000000..dc48af4a9f
--- /dev/null
+++ b/volk/lib/constants.c.in
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2013 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <volk/constants.h>
+
+char*
+volk_prefix()
+{
+ return "@prefix@";
+}
+
+char*
+volk_build_date()
+{
+ return "@BUILD_DATE@";
+}
+
+char*
+volk_version()
+{
+ return "@VERSION@";
+}
+
+char*
+volk_c_compiler()
+{
+ return "@cmake_c_compiler_version@";
+}
+
+char*
+volk_compiler_flags()
+{
+ return "@COMPILER_INFO@";
+}
+
+char*
+volk_available_machines()
+{
+ return "@available_machines@";
+}
diff --git a/volk/lib/qa_utils.cc b/volk/lib/qa_utils.cc
index 17164a4ec6..336a4ab32b 100644
--- a/volk/lib/qa_utils.cc
+++ b/volk/lib/qa_utils.cc
@@ -265,9 +265,10 @@ bool run_volk_tests(volk_func_desc_t desc,
int vlen,
int iter,
std::vector<std::string> *best_arch_vector = 0,
- std::string puppet_master_name = "NULL"
+ std::string puppet_master_name = "NULL",
+ bool benchmark_mode
) {
- std::cout << "RUN_VOLK_TESTS: " << name << std::endl;
+ std::cout << "RUN_VOLK_TESTS: " << name << "(" << vlen << "," << iter << ")" << std::endl;
const float tol_f = tol;
const unsigned int tol_i = static_cast<unsigned int>(tol);
@@ -275,7 +276,7 @@ bool run_volk_tests(volk_func_desc_t desc,
//first let's get a list of available architectures for the test
std::vector<std::string> arch_list = get_arch_list(desc);
- if(arch_list.size() < 2) {
+ if((!benchmark_mode) && (arch_list.size() < 2)) {
std::cout << "no architectures to test" << std::endl;
return false;
}
@@ -373,8 +374,8 @@ bool run_volk_tests(volk_func_desc_t desc,
}
end = clock();
- double arch_time = (double)(end-start)/(double)CLOCKS_PER_SEC;
- std::cout << arch_list[i] << " completed in " << arch_time << "s" << std::endl;
+ double arch_time = 1000.0 * (double)(end-start)/(double)CLOCKS_PER_SEC;
+ std::cout << arch_list[i] << " completed in " << arch_time << "ms" << std::endl;
profile_times.push_back(arch_time);
}
diff --git a/volk/lib/qa_utils.h b/volk/lib/qa_utils.h
index 0f17cdaa34..0ede962e41 100644
--- a/volk/lib/qa_utils.h
+++ b/volk/lib/qa_utils.h
@@ -21,12 +21,12 @@ volk_type_t volk_type_from_string(std::string);
float uniform(void);
void random_floats(float *buf, unsigned n);
-bool run_volk_tests(volk_func_desc_t, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string);
+bool run_volk_tests(volk_func_desc_t, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string, bool benchmark_mode=false);
#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) BOOST_AUTO_TEST_CASE(func##_test) { BOOST_CHECK_EQUAL(run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, 0, "NULL"), 0); }
-#define VOLK_PROFILE(func, tol, scalar, len, iter, results) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL")
-#define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func))
+#define VOLK_PROFILE(func, tol, scalar, len, iter, results, bnmode) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL", bnmode)
+#define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results, bnmode) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func), bnmode)
typedef void (*volk_fn_1arg)(void *, unsigned int, const char*); //one input, operate in place
typedef void (*volk_fn_2arg)(void *, void *, unsigned int, const char*);
typedef void (*volk_fn_3arg)(void *, void *, void *, unsigned int, const char*);
diff --git a/volk/tmpl/volk.tmpl.c b/volk/tmpl/volk.tmpl.c
index f915f157f6..431b1544aa 100644
--- a/volk/tmpl/volk.tmpl.c
+++ b/volk/tmpl/volk.tmpl.c
@@ -56,6 +56,43 @@ struct volk_machine *get_machine(void) {
}
}
+void volk_list_machines(void)
+{
+ extern struct volk_machine *volk_machines[];
+ extern unsigned int n_volk_machines;
+
+ unsigned int i;
+ for(i=0; i<n_volk_machines; i++) {
+ if(!(volk_machines[i]->caps & (~volk_get_lvarch()))) {
+ printf("%s;", volk_machines[i]->name);
+ }
+ }
+ printf("\n");
+}
+
+const char* volk_get_machine(void)
+{
+ extern struct volk_machine *volk_machines[];
+ extern unsigned int n_volk_machines;
+ static struct volk_machine *machine = NULL;
+
+ if(machine != NULL)
+ return machine->name;
+ else {
+ unsigned int max_score = 0;
+ unsigned int i;
+ for(i=0; i<n_volk_machines; i++) {
+ if(!(volk_machines[i]->caps & (~volk_get_lvarch()))) {
+ if(volk_machines[i]->caps > max_score) {
+ max_score = volk_machines[i]->caps;
+ machine = volk_machines[i];
+ }
+ }
+ }
+ return machine->name;
+ }
+}
+
size_t volk_get_alignment(void)
{
get_machine(); //ensures alignment is set
diff --git a/volk/tmpl/volk.tmpl.h b/volk/tmpl/volk.tmpl.h
index 464b65598a..c8731ed321 100644
--- a/volk/tmpl/volk.tmpl.h
+++ b/volk/tmpl/volk.tmpl.h
@@ -40,6 +40,12 @@ typedef struct volk_func_desc
const size_t n_impls;
} volk_func_desc_t;
+//! Prints a list of machines available
+VOLK_API void volk_list_machines(void);
+
+//! Returns the name of the machine this instance will use
+VOLK_API const char* volk_get_machine(void);
+
//! Get the machine alignment in bytes
VOLK_API size_t volk_get_alignment(void);