├── examples
├── README
└── top_block.py
├── docs
├── doxygen
│ ├── other
│ │ ├── group_defs.dox
│ │ └── main_page.dox
│ ├── doxyxml
│ │ ├── generated
│ │ │ ├── __init__.py
│ │ │ ├── index.py
│ │ │ └── indexsuper.py
│ │ ├── text.py
│ │ ├── __init__.py
│ │ ├── base.py
│ │ └── doxyindex.py
│ ├── CMakeLists.txt
│ └── swig_doc.py
├── README.devsync
└── CMakeLists.txt
├── swig
├── devsync_swig.i
└── CMakeLists.txt
├── grc
├── devsync_alligner.xml
├── devsync_rms_normalization.xml
├── CMakeLists.txt
└── devsync_peak_detector.xml
├── cmake
├── Modules
│ ├── devsyncConfig.cmake
│ ├── FindCppUnit.cmake
│ ├── FindGnuradioRuntime.cmake
│ ├── GrPlatform.cmake
│ ├── GrTest.cmake
│ ├── CMakeParseArgumentsCopy.cmake
│ ├── GrPython.cmake
│ ├── GrSwig.cmake
│ └── UseSWIG.cmake
└── cmake_uninstall.cmake.in
├── apps
└── CMakeLists.txt
├── include
└── devsync
│ ├── CMakeLists.txt
│ ├── api.h
│ ├── log.h
│ ├── alligner.h
│ ├── rms_normalization.h
│ └── peak_detector.h
├── python
├── __init__.py
├── build_utils_codes.py
├── CMakeLists.txt
└── build_utils.py
├── lib
├── rms_normalization_impl.h
├── peak_detector_impl.h
├── alligner_impl.h
├── CMakeLists.txt
├── rms_normalization_impl.cc
├── alligner_impl.cc
└── peak_detector_impl.cc
├── README.md
└── CMakeLists.txt
/examples/README:
--------------------------------------------------------------------------------
1 | It is considered good practice to add examples in here to demonstrate the
2 | functionality of your OOT module. Python scripts, GRC flow graphs or other
3 | code can go here.
4 |
5 |
--------------------------------------------------------------------------------
/docs/doxygen/other/group_defs.dox:
--------------------------------------------------------------------------------
1 | /*!
2 | * \defgroup block GNU Radio DEVSYNC C++ Signal Processing Blocks
3 | * \brief All C++ blocks that can be used from the DEVSYNC GNU Radio
4 | * module are listed here or in the subcategories below.
5 | *
6 | */
7 |
8 |
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/generated/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Contains generated files produced by generateDS.py.
3 |
4 | These do the real work of parsing the doxygen xml files but the
5 | resultant classes are not very friendly to navigate so the rest of the
6 | doxyxml module processes them further.
7 | """
8 |
--------------------------------------------------------------------------------
/docs/doxygen/other/main_page.dox:
--------------------------------------------------------------------------------
1 | /*! \mainpage
2 |
3 | Welcome to the GNU Radio DEVSYNC Block
4 |
5 | This is the intro page for the Doxygen manual generated for the DEVSYNC
6 | block (docs/doxygen/other/main_page.dox). Edit it to add more detailed
7 | documentation about the new GNU Radio modules contained in this
8 | project.
9 |
10 | */
11 |
--------------------------------------------------------------------------------
/docs/README.devsync:
--------------------------------------------------------------------------------
1 | This is the devsync-write-a-block package meant as a guide to building
2 | out-of-tree packages. To use the devsync blocks, the Python namespaces
3 | is in 'devsync', which is imported as:
4 |
5 | import devsync
6 |
7 | See the Doxygen documentation for details about the blocks available
8 | in this package. A quick listing of the details can be found in Python
9 | after importing by using:
10 |
11 | help(devsync)
12 |
--------------------------------------------------------------------------------
/swig/devsync_swig.i:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 |
3 | #define DEVSYNC_API
4 |
5 | %include "gnuradio.i" // the common stuff
6 |
7 | //load generated python docstrings
8 | %include "devsync_swig_doc.i"
9 |
10 | %{
11 | #include "devsync/alligner.h"
12 | #include "devsync/peak_detector.h"
13 | #include "devsync/rms_normalization.h"
14 | %}
15 |
16 |
17 | %include "devsync/alligner.h"
18 | GR_SWIG_BLOCK_MAGIC2(devsync, alligner);
19 | %include "devsync/peak_detector.h"
20 | GR_SWIG_BLOCK_MAGIC2(devsync, peak_detector);
21 | %include "devsync/rms_normalization.h"
22 | GR_SWIG_BLOCK_MAGIC2(devsync, rms_normalization);
23 |
--------------------------------------------------------------------------------
/grc/devsync_alligner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | alligner
4 | devsync_alligner
5 | [devsync]
6 | import devsync
7 | devsync.alligner($num_streams)
8 |
9 | Number of streams
10 | num_streams
11 | int
12 |
13 |
14 | in
15 | complex
16 | $num_streams
17 |
18 |
19 | phase_init
20 | message
21 |
22 |
23 | out
24 | complex
25 | $num_streams
26 |
27 |
28 |
--------------------------------------------------------------------------------
/grc/devsync_rms_normalization.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | rms_normalization
4 | devsync_rms_normalization
5 | [devsync]
6 | import devsync
7 | devsync.rms_normalization($num_streams, $vlen)
8 |
9 | Num Streams
10 | num_streams
11 | 2
12 | int
13 |
14 |
15 | Vec Length
16 | vlen
17 | 1
18 | int
19 |
20 |
21 | in
22 | complex
23 | $vlen
24 | $num_streams
25 |
26 |
27 | out
28 | complex
29 | $vlen
30 | $num_streams
31 |
32 |
33 |
--------------------------------------------------------------------------------
/cmake/Modules/devsyncConfig.cmake:
--------------------------------------------------------------------------------
1 | INCLUDE(FindPkgConfig)
2 | PKG_CHECK_MODULES(PC_DEVSYNC devsync)
3 |
4 | FIND_PATH(
5 | DEVSYNC_INCLUDE_DIRS
6 | NAMES devsync/api.h
7 | HINTS $ENV{DEVSYNC_DIR}/include
8 | ${PC_DEVSYNC_INCLUDEDIR}
9 | PATHS ${CMAKE_INSTALL_PREFIX}/include
10 | /usr/local/include
11 | /usr/include
12 | )
13 |
14 | FIND_LIBRARY(
15 | DEVSYNC_LIBRARIES
16 | NAMES gnuradio-devsync
17 | HINTS $ENV{DEVSYNC_DIR}/lib
18 | ${PC_DEVSYNC_LIBDIR}
19 | PATHS ${CMAKE_INSTALL_PREFIX}/lib
20 | ${CMAKE_INSTALL_PREFIX}/lib64
21 | /usr/local/lib
22 | /usr/local/lib64
23 | /usr/lib
24 | /usr/lib64
25 | )
26 |
27 | INCLUDE(FindPackageHandleStandardArgs)
28 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(DEVSYNC DEFAULT_MSG DEVSYNC_LIBRARIES DEVSYNC_INCLUDE_DIRS)
29 | MARK_AS_ADVANCED(DEVSYNC_LIBRARIES DEVSYNC_INCLUDE_DIRS)
30 |
31 |
--------------------------------------------------------------------------------
/apps/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | include(GrPython)
21 |
22 | GR_PYTHON_INSTALL(
23 | PROGRAMS
24 | DESTINATION bin
25 | )
26 |
--------------------------------------------------------------------------------
/grc/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | install(FILES
21 | devsync_alligner.xml
22 | devsync_peak_detector.xml
23 | devsync_rms_normalization.xml DESTINATION share/gnuradio/grc/blocks
24 | )
25 |
--------------------------------------------------------------------------------
/grc/devsync_peak_detector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | peak_detector
4 | devsync_peak_detector
5 | [devsync]
6 | import devsync
7 | devsync.peak_detector($num_streams, $win, $scale, $inf, $disc_samp)
8 |
9 | Num Streams
10 | num_streams
11 | 2
12 | int
13 |
14 |
15 | Window
16 | win
17 | 100
18 | int
19 |
20 |
21 | Discarted Samples
22 | disc_samp
23 | 100
24 | int
25 |
26 |
27 | Scale
28 | scale
29 | 1
30 | float
31 |
32 |
33 | Influence
34 | inf
35 | 0
36 | float
37 |
38 |
39 | in
40 | complex
41 | $num_streams
42 |
43 |
44 | shifts_out
45 | message
46 |
47 |
48 |
--------------------------------------------------------------------------------
/include/devsync/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011,2012 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Install public header files
22 | ########################################################################
23 | install(FILES
24 | api.h
25 | alligner.h
26 | peak_detector.h
27 | log.h
28 | rms_normalization.h DESTINATION include/devsync
29 | )
30 |
--------------------------------------------------------------------------------
/cmake/Modules/FindCppUnit.cmake:
--------------------------------------------------------------------------------
1 | # http://www.cmake.org/pipermail/cmake/2006-October/011446.html
2 | # Modified to use pkg config and use standard var names
3 |
4 | #
5 | # Find the CppUnit includes and library
6 | #
7 | # This module defines
8 | # CPPUNIT_INCLUDE_DIR, where to find tiff.h, etc.
9 | # CPPUNIT_LIBRARIES, the libraries to link against to use CppUnit.
10 | # CPPUNIT_FOUND, If false, do not try to use CppUnit.
11 |
12 | INCLUDE(FindPkgConfig)
13 | PKG_CHECK_MODULES(PC_CPPUNIT "cppunit")
14 |
15 | FIND_PATH(CPPUNIT_INCLUDE_DIRS
16 | NAMES cppunit/TestCase.h
17 | HINTS ${PC_CPPUNIT_INCLUDE_DIR}
18 | ${CMAKE_INSTALL_PREFIX}/include
19 | PATHS
20 | /usr/local/include
21 | /usr/include
22 | )
23 |
24 | FIND_LIBRARY(CPPUNIT_LIBRARIES
25 | NAMES cppunit
26 | HINTS ${PC_CPPUNIT_LIBDIR}
27 | ${CMAKE_INSTALL_PREFIX}/lib
28 | ${CMAKE_INSTALL_PREFIX}/lib64
29 | PATHS
30 | ${CPPUNIT_INCLUDE_DIRS}/../lib
31 | /usr/local/lib
32 | /usr/lib
33 | )
34 |
35 | LIST(APPEND CPPUNIT_LIBRARIES ${CMAKE_DL_LIBS})
36 |
37 | INCLUDE(FindPackageHandleStandardArgs)
38 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(CPPUNIT DEFAULT_MSG CPPUNIT_LIBRARIES CPPUNIT_INCLUDE_DIRS)
39 | MARK_AS_ADVANCED(CPPUNIT_LIBRARIES CPPUNIT_INCLUDE_DIRS)
40 |
--------------------------------------------------------------------------------
/python/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2008,2009 Free Software Foundation, Inc.
3 | #
4 | # This application is free software; you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation; either version 3, or (at your option)
7 | # any later version.
8 | #
9 | # This application is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License along
15 | # with this program; if not, write to the Free Software Foundation, Inc.,
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 | #
18 |
19 | # The presence of this file turns this directory into a Python package
20 |
21 | '''
22 | This is the GNU Radio DEVSYNC module. Place your Python package
23 | description here (python/__init__.py).
24 | '''
25 |
26 | # import swig generated symbols into the devsync namespace
27 | try:
28 | # this might fail if the module is python-only
29 | from devsync_swig import *
30 | except ImportError:
31 | pass
32 |
33 | # import any pure python here
34 | #
35 |
--------------------------------------------------------------------------------
/cmake/Modules/FindGnuradioRuntime.cmake:
--------------------------------------------------------------------------------
1 | INCLUDE(FindPkgConfig)
2 | PKG_CHECK_MODULES(PC_GNURADIO_RUNTIME gnuradio-runtime)
3 |
4 | if(PC_GNURADIO_RUNTIME_FOUND)
5 | # look for include files
6 | FIND_PATH(
7 | GNURADIO_RUNTIME_INCLUDE_DIRS
8 | NAMES gnuradio/top_block.h
9 | HINTS $ENV{GNURADIO_RUNTIME_DIR}/include
10 | ${PC_GNURADIO_RUNTIME_INCLUDE_DIRS}
11 | ${CMAKE_INSTALL_PREFIX}/include
12 | PATHS /usr/local/include
13 | /usr/include
14 | )
15 |
16 | # look for libs
17 | FIND_LIBRARY(
18 | GNURADIO_RUNTIME_LIBRARIES
19 | NAMES gnuradio-runtime
20 | HINTS $ENV{GNURADIO_RUNTIME_DIR}/lib
21 | ${PC_GNURADIO_RUNTIME_LIBDIR}
22 | ${CMAKE_INSTALL_PREFIX}/lib/
23 | ${CMAKE_INSTALL_PREFIX}/lib64/
24 | PATHS /usr/local/lib
25 | /usr/local/lib64
26 | /usr/lib
27 | /usr/lib64
28 | )
29 |
30 | set(GNURADIO_RUNTIME_FOUND ${PC_GNURADIO_RUNTIME_FOUND})
31 | endif(PC_GNURADIO_RUNTIME_FOUND)
32 |
33 | INCLUDE(FindPackageHandleStandardArgs)
34 | # do not check GNURADIO_RUNTIME_INCLUDE_DIRS, is not set when default include path us used.
35 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_RUNTIME DEFAULT_MSG GNURADIO_RUNTIME_LIBRARIES)
36 | MARK_AS_ADVANCED(GNURADIO_RUNTIME_LIBRARIES GNURADIO_RUNTIME_INCLUDE_DIRS)
37 |
--------------------------------------------------------------------------------
/cmake/cmake_uninstall.cmake.in:
--------------------------------------------------------------------------------
1 | # http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
2 |
3 | IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
4 | MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
5 | ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
6 |
7 | FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
8 | STRING(REGEX REPLACE "\n" ";" files "${files}")
9 | FOREACH(file ${files})
10 | MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
11 | IF(EXISTS "$ENV{DESTDIR}${file}")
12 | EXEC_PROGRAM(
13 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
14 | OUTPUT_VARIABLE rm_out
15 | RETURN_VALUE rm_retval
16 | )
17 | IF(NOT "${rm_retval}" STREQUAL 0)
18 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
19 | ENDIF(NOT "${rm_retval}" STREQUAL 0)
20 | ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}")
21 | EXEC_PROGRAM(
22 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
23 | OUTPUT_VARIABLE rm_out
24 | RETURN_VALUE rm_retval
25 | )
26 | IF(NOT "${rm_retval}" STREQUAL 0)
27 | MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
28 | ENDIF(NOT "${rm_retval}" STREQUAL 0)
29 | ELSE(EXISTS "$ENV{DESTDIR}${file}")
30 | MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
31 | ENDIF(EXISTS "$ENV{DESTDIR}${file}")
32 | ENDFOREACH(file)
33 |
--------------------------------------------------------------------------------
/docs/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Setup dependencies
22 | ########################################################################
23 | find_package(Doxygen)
24 |
25 | ########################################################################
26 | # Begin conditional configuration
27 | ########################################################################
28 | if(ENABLE_DOXYGEN)
29 |
30 | ########################################################################
31 | # Add subdirectories
32 | ########################################################################
33 | add_subdirectory(doxygen)
34 |
35 | endif(ENABLE_DOXYGEN)
36 |
--------------------------------------------------------------------------------
/include/devsync/api.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifndef INCLUDED_DEVSYNC_API_H
21 | #define INCLUDED_DEVSYNC_API_H
22 |
23 | #include
24 |
25 | #ifdef gnuradio_devsync_EXPORTS
26 | # define DEVSYNC_API __GR_ATTR_EXPORT
27 | #else
28 | # define DEVSYNC_API __GR_ATTR_IMPORT
29 | #endif
30 |
31 | typedef enum{
32 | NO_SYNC=0,
33 | PREAMBLE=1,
34 | POST_PREAMBLE=2,
35 | SYNC=3,
36 | IN_SYNC=4,
37 | }state;
38 |
39 | typedef enum{
40 | SYNCING=0,
41 | FIRST_SYNC_NOW=1,
42 | FIRST_SYNC_FOUND=2,
43 | FIRST_BUFFER_FILL=3,
44 | SYNCED=4,
45 | NO_PHASE_DIFF=5,
46 | FINE_SYNC=6,
47 | WINDOW_FILL=7,
48 | FIRST_SYNCING=8
49 | }overall_state;
50 |
51 | #define ENABLE_DEBUG_MSG 1
52 | #endif /* INCLUDED_DEVSYNC_API_H */
53 |
--------------------------------------------------------------------------------
/python/build_utils_codes.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2004 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 |
22 | def i_code (code3):
23 | return code3[0]
24 |
25 | def o_code (code3):
26 | if len (code3) >= 2:
27 | return code3[1]
28 | else:
29 | return code3[0]
30 |
31 | def tap_code (code3):
32 | if len (code3) >= 3:
33 | return code3[2]
34 | else:
35 | return code3[0]
36 |
37 | def i_type (code3):
38 | return char_to_type[i_code (code3)]
39 |
40 | def o_type (code3):
41 | return char_to_type[o_code (code3)]
42 |
43 | def tap_type (code3):
44 | return char_to_type[tap_code (code3)]
45 |
46 |
47 | char_to_type = {}
48 | char_to_type['s'] = 'short'
49 | char_to_type['i'] = 'int'
50 | char_to_type['f'] = 'float'
51 | char_to_type['c'] = 'gr_complex'
52 | char_to_type['b'] = 'unsigned char'
53 |
--------------------------------------------------------------------------------
/lib/rms_normalization_impl.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifndef INCLUDED_DEVSYNC_RMS_NORMALIZATION_IMPL_H
21 | #define INCLUDED_DEVSYNC_RMS_NORMALIZATION_IMPL_H
22 |
23 | #include
24 |
25 | namespace gr
26 | {
27 | namespace devsync
28 | {
29 |
30 | class rms_normalization_impl : public rms_normalization
31 | {
32 | private:
33 | size_t d_vlen;
34 | size_t d_num_streams;
35 |
36 | public:
37 | rms_normalization_impl (size_t num_streams, size_t vlen);
38 | ~rms_normalization_impl ();
39 |
40 | int
41 | work (int noutput_items, gr_vector_const_void_star &input_items,
42 | gr_vector_void_star &output_items);
43 | };
44 |
45 | } // namespace devsync
46 | } // namespace gr
47 |
48 | #endif /* INCLUDED_DEVSYNC_RMS_NORMALIZATION_IMPL_H */
49 |
50 |
--------------------------------------------------------------------------------
/include/devsync/log.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifndef LOG_H_
21 | #define LOG_H_
22 |
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 |
30 | //#if ENABLE_DEBUG_MSG
31 | #define LOG_INFO(M, ...) \
32 | fprintf(stderr, "[INFO]: " M " \n", ##__VA_ARGS__)
33 |
34 | //#else
35 | //#define LOG_INFO(M, ...)
36 | //#endif
37 |
38 | #define LOG_ERROR(M, ...) \
39 | fprintf(stderr, "[ERROR] %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
40 |
41 | #define LOG_WARN(M, ...) \
42 | fprintf(stderr, "[WARNING] %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
43 |
44 | #if ENABLE_DEBUG_MSG
45 | #define LOG_DEBUG(M, ...) \
46 | fprintf(stderr, "[DEBUG]: " M "\n", ##__VA_ARGS__)
47 | #else
48 | #define LOG_DEBUG(M, ...)
49 | #endif
50 |
51 |
52 | #endif /* UTILS_LOG_H_ */
53 |
--------------------------------------------------------------------------------
/python/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Include python install macros
22 | ########################################################################
23 | include(GrPython)
24 | if(NOT PYTHONINTERP_FOUND)
25 | return()
26 | endif()
27 |
28 | ########################################################################
29 | # Install python sources
30 | ########################################################################
31 | GR_PYTHON_INSTALL(
32 | FILES
33 | __init__.py
34 | DESTINATION ${GR_PYTHON_DIR}/devsync
35 | )
36 |
37 | ########################################################################
38 | # Handle the unit tests
39 | ########################################################################
40 | include(GrTest)
41 |
42 | set(GR_TEST_TARGET_DEPS gnuradio-devsync)
43 | set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig)
44 |
--------------------------------------------------------------------------------
/include/devsync/alligner.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 |
21 | #ifndef INCLUDED_DEVSYNC_ALLIGNER_H
22 | #define INCLUDED_DEVSYNC_ALLIGNER_H
23 |
24 | #include
25 | #include
26 |
27 | namespace gr {
28 | namespace devsync {
29 |
30 | /*!
31 | * \brief Sample alligner block
32 | * \ingroup devsync
33 | *
34 | * \details
35 | * This block alligns the samples of the receiving streams
36 | * according to the information provided by the peak detector
37 | * block. One stream is taken as the reference stream, and
38 | * an offset is applied to the rest of the streams so that
39 | * they become alligned in phase.
40 | */
41 | class DEVSYNC_API alligner : virtual public gr::sync_block
42 | {
43 | public:
44 | typedef boost::shared_ptr sptr;
45 |
46 | /*!
47 | * Build the alligner block
48 | *
49 | * \param num_streams (size_t) Total number of receiving streams
50 | */
51 | static sptr make(size_t num_streams);
52 | };
53 |
54 | } // namespace devsync
55 | } // namespace gr
56 |
57 | #endif /* INCLUDED_DEVSYNC_ALLIGNER_H */
58 |
59 |
--------------------------------------------------------------------------------
/include/devsync/rms_normalization.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 |
21 | #ifndef INCLUDED_DEVSYNC_RMS_NORMALIZATION_H
22 | #define INCLUDED_DEVSYNC_RMS_NORMALIZATION_H
23 |
24 | #include
25 | #include
26 |
27 | namespace gr {
28 | namespace devsync {
29 |
30 | /*!
31 | * \brief RMS normalization block
32 | * \ingroup devsync
33 | *
34 | *\details
35 | * This block performs a simple RMS normalization method to bring
36 | * the amplitudes of all receiving channels at the same level for
37 | * effective peak detection.
38 | */
39 | class DEVSYNC_API rms_normalization : virtual public gr::sync_block
40 | {
41 | public:
42 | typedef boost::shared_ptr sptr;
43 |
44 | /*!
45 | * Build the RMS normalization block
46 | *
47 | * \param num_streams (size_t) Total number of receiving streams
48 | * \param vlen (size_t) Length of window over which the normalization
49 | * will take place.
50 | *
51 | */
52 | static sptr make(size_t num_streams, size_t vlen);
53 | };
54 |
55 | } // namespace devsync
56 | } // namespace gr
57 |
58 | #endif /* INCLUDED_DEVSYNC_RMS_NORMALIZATION_H */
59 |
60 |
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/text.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2010 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 | """
22 | Utilities for extracting text from generated classes.
23 | """
24 |
25 | def is_string(txt):
26 | if isinstance(txt, str):
27 | return True
28 | try:
29 | if isinstance(txt, unicode):
30 | return True
31 | except NameError:
32 | pass
33 | return False
34 |
35 | def description(obj):
36 | if obj is None:
37 | return None
38 | return description_bit(obj).strip()
39 |
40 | def description_bit(obj):
41 | if hasattr(obj, 'content'):
42 | contents = [description_bit(item) for item in obj.content]
43 | result = ''.join(contents)
44 | elif hasattr(obj, 'content_'):
45 | contents = [description_bit(item) for item in obj.content_]
46 | result = ''.join(contents)
47 | elif hasattr(obj, 'value'):
48 | result = description_bit(obj.value)
49 | elif is_string(obj):
50 | return obj
51 | else:
52 | raise StandardError('Expecting a string or something with content, content_ or value attribute')
53 | # If this bit is a paragraph then add one some line breaks.
54 | if hasattr(obj, 'name') and obj.name == 'para':
55 | result += "\n\n"
56 | return result
57 |
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/generated/index.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Generated Mon Feb 9 19:08:05 2009 by generateDS.py.
5 | """
6 |
7 | from xml.dom import minidom
8 |
9 | import os
10 | import sys
11 | import compound
12 |
13 | import indexsuper as supermod
14 |
15 | class DoxygenTypeSub(supermod.DoxygenType):
16 | def __init__(self, version=None, compound=None):
17 | supermod.DoxygenType.__init__(self, version, compound)
18 |
19 | def find_compounds_and_members(self, details):
20 | """
21 | Returns a list of all compounds and their members which match details
22 | """
23 |
24 | results = []
25 | for compound in self.compound:
26 | members = compound.find_members(details)
27 | if members:
28 | results.append([compound, members])
29 | else:
30 | if details.match(compound):
31 | results.append([compound, []])
32 |
33 | return results
34 |
35 | supermod.DoxygenType.subclass = DoxygenTypeSub
36 | # end class DoxygenTypeSub
37 |
38 |
39 | class CompoundTypeSub(supermod.CompoundType):
40 | def __init__(self, kind=None, refid=None, name='', member=None):
41 | supermod.CompoundType.__init__(self, kind, refid, name, member)
42 |
43 | def find_members(self, details):
44 | """
45 | Returns a list of all members which match details
46 | """
47 |
48 | results = []
49 |
50 | for member in self.member:
51 | if details.match(member):
52 | results.append(member)
53 |
54 | return results
55 |
56 | supermod.CompoundType.subclass = CompoundTypeSub
57 | # end class CompoundTypeSub
58 |
59 |
60 | class MemberTypeSub(supermod.MemberType):
61 |
62 | def __init__(self, kind=None, refid=None, name=''):
63 | supermod.MemberType.__init__(self, kind, refid, name)
64 |
65 | supermod.MemberType.subclass = MemberTypeSub
66 | # end class MemberTypeSub
67 |
68 |
69 | def parse(inFilename):
70 |
71 | doc = minidom.parse(inFilename)
72 | rootNode = doc.documentElement
73 | rootObj = supermod.DoxygenType.factory()
74 | rootObj.build(rootNode)
75 |
76 | return rootObj
77 |
78 |
--------------------------------------------------------------------------------
/docs/doxygen/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Create the doxygen configuration file
22 | ########################################################################
23 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} top_srcdir)
24 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} top_builddir)
25 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} abs_top_srcdir)
26 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} abs_top_builddir)
27 |
28 | set(HAVE_DOT ${DOXYGEN_DOT_FOUND})
29 | set(enable_html_docs YES)
30 | set(enable_latex_docs NO)
31 | set(enable_xml_docs YES)
32 |
33 | configure_file(
34 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
35 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
36 | @ONLY)
37 |
38 | set(BUILT_DIRS ${CMAKE_CURRENT_BINARY_DIR}/xml ${CMAKE_CURRENT_BINARY_DIR}/html)
39 |
40 | ########################################################################
41 | # Make and install doxygen docs
42 | ########################################################################
43 | add_custom_command(
44 | OUTPUT ${BUILT_DIRS}
45 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
46 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
47 | COMMENT "Generating documentation with doxygen"
48 | )
49 |
50 | add_custom_target(doxygen_target ALL DEPENDS ${BUILT_DIRS})
51 |
52 | install(DIRECTORY ${BUILT_DIRS} DESTINATION ${GR_PKG_DOC_DIR})
53 |
--------------------------------------------------------------------------------
/cmake/Modules/GrPlatform.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | if(DEFINED __INCLUDED_GR_PLATFORM_CMAKE)
21 | return()
22 | endif()
23 | set(__INCLUDED_GR_PLATFORM_CMAKE TRUE)
24 |
25 | ########################################################################
26 | # Setup additional defines for OS types
27 | ########################################################################
28 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
29 | set(LINUX TRUE)
30 | endif()
31 |
32 | if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/debian_version")
33 | set(DEBIAN TRUE)
34 | endif()
35 |
36 | if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/redhat-release")
37 | set(REDHAT TRUE)
38 | endif()
39 |
40 | if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/slackware-version")
41 | set(SLACKWARE TRUE)
42 | endif()
43 |
44 | ########################################################################
45 | # when the library suffix should be 64 (applies to redhat linux family)
46 | ########################################################################
47 | if (REDHAT OR SLACKWARE)
48 | set(LIB64_CONVENTION TRUE)
49 | endif()
50 |
51 | if(NOT DEFINED LIB_SUFFIX AND LIB64_CONVENTION AND CMAKE_SYSTEM_PROCESSOR MATCHES "64$")
52 | set(LIB_SUFFIX 64)
53 | endif()
54 |
55 | ########################################################################
56 | # Detect /lib versus /lib64
57 | ########################################################################
58 | if (CMAKE_INSTALL_LIBDIR MATCHES lib64)
59 | set(LIB_SUFFIX 64)
60 | endif()
61 |
62 | set(LIB_SUFFIX ${LIB_SUFFIX} CACHE STRING "lib directory suffix")
63 |
--------------------------------------------------------------------------------
/lib/peak_detector_impl.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifndef INCLUDED_DEVSYNC_PEAK_DETECTOR_IMPL_H
21 | #define INCLUDED_DEVSYNC_PEAK_DETECTOR_IMPL_H
22 |
23 | #include
24 | #include
25 | namespace gr
26 | {
27 | namespace devsync
28 | {
29 |
30 | class peak_detector_impl : public peak_detector
31 | {
32 | private:
33 | size_t d_num_streams;
34 | size_t d_window;
35 | float d_scale;
36 | float d_influence;
37 | size_t d_sample_counter;
38 | overall_state ov_state;
39 | size_t d_synced_streams;
40 | size_t d_ref_stream;
41 | size_t *d_sample_difference;
42 | state *d_state_vector;
43 | size_t d_cyc_buf_next_idx;
44 | size_t *d_zero_counter;
45 | size_t d_discarted_samples_counter;
46 | size_t d_discarted_samples;
47 | size_t d_ninput_items;
48 | size_t d_noutput_items;
49 | float *d_amp_thres;
50 | std::vector> filteredY;
51 | float *avgFilter;
52 | float *stdFilter;
53 | float *d_max_abs_sample;
54 | gr_complex *d_max_sample;
55 | float *d_sum;
56 | float *d_sumsqr;
57 | pmt::pmt_t d_phase_shifts_out;
58 |
59 | public:
60 | peak_detector_impl (size_t num_streams, size_t window, float scale,
61 | float influence, size_t discarted_samples);
62 | ~peak_detector_impl ();
63 | void
64 | mean_std (int stream, float discarded_val);
65 |
66 | int
67 | work (int noutput_items, gr_vector_const_void_star &input_items,
68 | gr_vector_void_star &output_items);
69 | };
70 |
71 | } // namespace devsync
72 | } // namespace gr
73 |
74 | #endif /* INCLUDED_DEVSYNC_PEAK_DETECTOR_IMPL_H */
75 |
76 |
--------------------------------------------------------------------------------
/lib/alligner_impl.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifndef INCLUDED_DEVSYNC_ALLIGNER_IMPL_H
21 | #define INCLUDED_DEVSYNC_ALLIGNER_IMPL_H
22 |
23 | #include
24 |
25 | namespace gr
26 | {
27 | namespace devsync
28 | {
29 |
30 | class alligner_impl : public alligner
31 | {
32 | private:
33 | size_t d_num_streams;
34 | size_t d_sample_counter;
35 | pmt::pmt_t d_phase_init;
36 | overall_state ov_state;
37 | size_t d_init_filled_streams;
38 | size_t d_num_delayed_streams;
39 | gr_complex** d_delayed_samples_buf;
40 | size_t *d_sample_difference;
41 | size_t *d_cyc_buf_next_idx; /*Index of available next sample to be copied to the output stream*/
42 | size_t *d_filled_buf_rem; /*How many bytes remaining for the buffer of the stream
43 | to fill initially*/
44 | double *d_fine_phase_diffs;
45 | std::complex* d_fine_complex_shifts;
46 | boost::shared_ptr d_init_thread;
47 | size_t d_ref_stream;
48 |
49 | public:
50 | alligner_impl (size_t num_streams);
51 | ~alligner_impl ();
52 |
53 | void
54 | recv_phase_shifts (pmt::pmt_t msg);
55 | void
56 | setup_delays ();
57 | void
58 | initial_buff_fill (gr_vector_const_void_star &input_items,
59 | gr_vector_void_star &out, int noutput_items);
60 | void
61 | delay_samples (gr_vector_const_void_star &input_items,
62 | gr_vector_void_star &output_items, int noutput_items);
63 |
64 | int
65 | work (int noutput_items, gr_vector_const_void_star &input_items,
66 | gr_vector_void_star &output_items);
67 | };
68 |
69 | } // namespace devsync
70 | } // namespace gr
71 |
72 | #endif /* INCLUDED_DEVSYNC_ALLIGNER_IMPL_H */
73 |
74 |
--------------------------------------------------------------------------------
/lib/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011,2012,2016 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Setup library
22 | ########################################################################
23 | include(GrPlatform) #define LIB_SUFFIX
24 |
25 | include_directories(${Boost_INCLUDE_DIR})
26 | include_directories(${ARMADILLO_INCLUDE_DIRS})
27 | link_directories(${Boost_LIBRARY_DIRS})
28 | link_directories(${Armadillo_LIBRARY_DIRS})
29 |
30 | list(APPEND devsync_sources
31 | alligner_impl.cc
32 | peak_detector_impl.cc
33 | rms_normalization_impl.cc
34 | )
35 |
36 | set(devsync_sources "${devsync_sources}" PARENT_SCOPE)
37 | if(NOT devsync_sources)
38 | MESSAGE(STATUS "No C++ sources... skipping lib/")
39 | return()
40 | endif(NOT devsync_sources)
41 |
42 | add_library(gnuradio-devsync SHARED ${devsync_sources})
43 | target_link_libraries(gnuradio-devsync ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES})
44 | set_target_properties(gnuradio-devsync PROPERTIES DEFINE_SYMBOL "gnuradio_devsync_EXPORTS")
45 |
46 | if(APPLE)
47 | set_target_properties(gnuradio-devsync PROPERTIES
48 | INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib"
49 | )
50 | endif(APPLE)
51 |
52 | ########################################################################
53 | # Install built library files
54 | ########################################################################
55 | include(GrMiscUtils)
56 | GR_LIBRARY_FOO(gnuradio-devsync RUNTIME_COMPONENT "devsync_runtime" DEVEL_COMPONENT "devsync_devel")
57 |
58 | ########################################################################
59 | # Print summary
60 | ########################################################################
61 | message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}")
62 | message(STATUS "Building for version: ${VERSION} / ${LIBVER}")
63 |
64 |
--------------------------------------------------------------------------------
/swig/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Check if there is C++ code at all
22 | ########################################################################
23 | if(NOT devsync_sources)
24 | MESSAGE(STATUS "No C++ sources... skipping swig/")
25 | return()
26 | endif(NOT devsync_sources)
27 |
28 | ########################################################################
29 | # Include swig generation macros
30 | ########################################################################
31 | find_package(SWIG)
32 | find_package(PythonLibs 2)
33 | if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND)
34 | return()
35 | endif()
36 | include(GrSwig)
37 | include(GrPython)
38 |
39 | ########################################################################
40 | # Setup swig generation
41 | ########################################################################
42 | foreach(incdir ${GNURADIO_RUNTIME_INCLUDE_DIRS})
43 | list(APPEND GR_SWIG_INCLUDE_DIRS ${incdir}/gnuradio/swig)
44 | endforeach(incdir)
45 |
46 | set(GR_SWIG_LIBRARIES gnuradio-devsync)
47 | set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/devsync_swig_doc.i)
48 | set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include)
49 |
50 | GR_SWIG_MAKE(devsync_swig devsync_swig.i)
51 |
52 | ########################################################################
53 | # Install the build swig module
54 | ########################################################################
55 | GR_SWIG_INSTALL(TARGETS devsync_swig DESTINATION ${GR_PYTHON_DIR}/devsync)
56 |
57 | ########################################################################
58 | # Install swig .i files for development
59 | ########################################################################
60 | install(
61 | FILES
62 | devsync_swig.i
63 | ${CMAKE_CURRENT_BINARY_DIR}/devsync_swig_doc.i
64 | DESTINATION ${GR_INCLUDE_DIR}/devsync/swig
65 | )
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## GR-DEVSYNC
2 | gr-devsync is an Out Of Tree module of GNURadio, designed to provide phase synchronization for multiple SDR devices.
3 |
4 | # Description
5 | The goal of this project is to provide a low-cost, extendable solution to phase synchronizing multiple SDR devices for use in MIMO scenarios. Apart from the antenna array to be synchronized, gr-devysnc also requires an SDR device with transmit capability. A known signal is transmitted, and received by all elements of the antenna array. Using crosscorrelation with the known sequence at the receiver, we detect the arrival of the signal at all channels, and provided that the signal is received at (almost) the same time from each one, we compensate digitally for the phase offset between them. For the purpose of this project, the long training sequence of the IEEE802.11 protocol is being used as the transmitted known signal. Also, it is assumed that the RX devices are synchronized in frequency.
6 |
7 | # Usage
8 | The transmitting element is placed at the far field side of the antenna array so that the signal arrives at the array as a plane wave. Also, it must be placed at a direction, such that the distance of the transmitting antenna to each of the receiving elements, is almost equal. For example, if the array is a linear array, the transmitting antenna should be placed at azimuth 90 and elevation 0, so that the signal arrives at the same time at all receiving elements.
9 |
10 | After the start of execution, a (user-defined) number of samples is discarded, and after, the noise floor estimation takes place. For this reason, and depending on the values defined by the user in the corresponding blocks, the transmission of the signal should occur a few seconds after the start of execution.
11 |
12 | Furthermore, an RMS normalization method is used to bring the receiving signals of the different channels on the same level, in order to compensate for possible amplitude offsets, which degrade the performance of the synchronizer.
13 |
14 | Please refer to the examples folder for a sample flowgraph of how the different blocks are combined.
15 |
16 | # Dependencies
17 | Apart from the dependencies of gnuradio, gr-devsync also requires the Armadillo library to build.
18 |
19 | # Installation
20 | gr-devsync uses the cmake tool for generating the appropriate Makefiles
21 |
22 | First create a build directory
23 |
24 |
25 | ```sh
26 | $ mkdir build
27 | ```
28 |
29 | Execute the cmake command with the appropriate arguments inside the build directory
30 |
31 | ```sh
32 | $ cmake ..
33 | ```
34 |
35 | And finally build the project
36 |
37 | ```sh
38 | $ make
39 | $ sudo make install
40 | ```
41 |
42 | # Contact
43 | For any information you will find me on the gnuradio and usrp lists, or email me at vardakis@csd.uoc.gr
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/__init__.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2010 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 | """
22 | Python interface to contents of doxygen xml documentation.
23 |
24 | Example use:
25 | See the contents of the example folder for the C++ and
26 | doxygen-generated xml used in this example.
27 |
28 | >>> # Parse the doxygen docs.
29 | >>> import os
30 | >>> this_dir = os.path.dirname(globals()['__file__'])
31 | >>> xml_path = this_dir + "/example/xml/"
32 | >>> di = DoxyIndex(xml_path)
33 |
34 | Get a list of all top-level objects.
35 |
36 | >>> print([mem.name() for mem in di.members()])
37 | [u'Aadvark', u'aadvarky_enough', u'main']
38 |
39 | Get all functions.
40 |
41 | >>> print([mem.name() for mem in di.in_category(DoxyFunction)])
42 | [u'aadvarky_enough', u'main']
43 |
44 | Check if an object is present.
45 |
46 | >>> di.has_member(u'Aadvark')
47 | True
48 | >>> di.has_member(u'Fish')
49 | False
50 |
51 | Get an item by name and check its properties.
52 |
53 | >>> aad = di.get_member(u'Aadvark')
54 | >>> print(aad.brief_description)
55 | Models the mammal Aadvark.
56 | >>> print(aad.detailed_description)
57 | Sadly the model is incomplete and cannot capture all aspects of an aadvark yet.
58 |
59 | This line is uninformative and is only to test line breaks in the comments.
60 | >>> [mem.name() for mem in aad.members()]
61 | [u'aadvarkness', u'print', u'Aadvark', u'get_aadvarkness']
62 | >>> aad.get_member(u'print').brief_description
63 | u'Outputs the vital aadvark statistics.'
64 |
65 | """
66 |
67 | from doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther
68 |
69 | def _test():
70 | import os
71 | this_dir = os.path.dirname(globals()['__file__'])
72 | xml_path = this_dir + "/example/xml/"
73 | di = DoxyIndex(xml_path)
74 | # Get the Aadvark class
75 | aad = di.get_member('Aadvark')
76 | aad.brief_description
77 | import doctest
78 | return doctest.testmod()
79 |
80 | if __name__ == "__main__":
81 | _test()
82 |
83 |
--------------------------------------------------------------------------------
/lib/rms_normalization_impl.cc:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifdef HAVE_CONFIG_H
21 | #include "config.h"
22 | #endif
23 |
24 | #include
25 | #include "rms_normalization_impl.h"
26 |
27 | #include
28 | #include
29 | using namespace arma;
30 | namespace gr
31 | {
32 | namespace devsync
33 | {
34 |
35 | rms_normalization::sptr
36 | rms_normalization::make (size_t num_streams, size_t vlen)
37 | {
38 | return gnuradio::get_initial_sptr (
39 | new rms_normalization_impl (num_streams, vlen));
40 | }
41 |
42 | rms_normalization_impl::rms_normalization_impl (size_t num_streams,
43 | size_t vlen) :
44 | gr::sync_block (
45 | "rms_normalization",
46 | gr::io_signature::make (num_streams, num_streams,
47 | sizeof(std::complex) * vlen),
48 | gr::io_signature::make (num_streams, num_streams,
49 | sizeof(std::complex) * vlen)),
50 | d_vlen (vlen),
51 | d_num_streams (num_streams)
52 | {
53 | }
54 |
55 | rms_normalization_impl::~rms_normalization_impl ()
56 | {
57 | }
58 |
59 | int
60 | rms_normalization_impl::work (int noutput_items,
61 | gr_vector_const_void_star &input_items,
62 | gr_vector_void_star &output_items)
63 | {
64 | std::complex **in = (std::complex **) &input_items[0];
65 |
66 | std::complex **out = (std::complex **) &output_items[0];
67 | for (int i = 0; i < noutput_items; i++) {
68 | cx_fmat batch (&in[0][i * d_vlen], 1, d_vlen, false, true);
69 | float ref = std::sqrt (sum (sum (pow (abs (batch), 2))) / d_vlen);
70 | memcpy (&out[0][i * d_vlen], &in[0][i * d_vlen],
71 | sizeof(std::complex) * d_vlen);
72 | for (int j = 1; j < d_num_streams; j++) {
73 | cx_fmat batch (&in[j][i * d_vlen], 1, d_vlen, false, true);
74 | float rms = std::sqrt (sum (sum (pow (abs (batch), 2))) / d_vlen);
75 | batch = batch * (ref / rms);
76 | memcpy (&out[j][i * d_vlen], batch.memptr (),
77 | sizeof(std::complex) * d_vlen);
78 | }
79 | }
80 | return noutput_items;
81 | }
82 |
83 | } /* namespace devsync */
84 | } /* namespace gr */
85 |
86 |
--------------------------------------------------------------------------------
/include/devsync/peak_detector.h:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 |
21 | #ifndef INCLUDED_DEVSYNC_PEAK_DETECTOR_H
22 | #define INCLUDED_DEVSYNC_PEAK_DETECTOR_H
23 |
24 | #include
25 | #include
26 |
27 | namespace gr {
28 | namespace devsync {
29 |
30 | /*!
31 | * \brief The peak detector block
32 | * \ingroup devsync
33 | *
34 | * \details This block performs a simple peak detection algorithm
35 | * on the output of the FFT filter blocks in order to detect the
36 | * peaks that correspond to the reception of the training sequence
37 | * by the receiving channels.
38 | *
39 | * The peak detection algorithm first makes a rough noise floor
40 | * estimation. Next, it attempts to detect peak values by keeping
41 | * a moving average of previous energy values. If the difference
42 | * in energy levels between the last and the new sample exceeds the
43 | * last sample's energy, scaled by a value, then a peak
44 | * is detected. The user also has the option, through the influence
45 | * parameter to dictate if the current sample's energy (influence = 1)
46 | * , or the moving average of the previous samples in the window
47 | * (influence = 0), will have the most effect on the calculations.
48 | *
49 | * The last stream on which a peak is detected, is taken as the
50 | * reference stream : all remaining streams will allign their samples
51 | * according to it. Apart from the coarse synchronization, in
52 | * sample level, between the streams, a fine synchronization also
53 | * takes place to account for phase differences smaller than a
54 | * sample. This is done by estimating the angle between the peak
55 | * value of the reference stream, and the rest of the streams.
56 | * All the information is passed through the message output to
57 | * the alligner block.
58 | *
59 | */
60 | class DEVSYNC_API peak_detector : virtual public gr::sync_block
61 | {
62 | public:
63 | typedef boost::shared_ptr sptr;
64 |
65 | /*!
66 | * Build the peak detection block
67 | *
68 | * \param num_streams (size_t) The total number of receiving streams
69 | * \param window (size_t) The length in samples of the window over which
70 | * the noise floor estimation at the beginning will occur
71 | * \param scale (float) Scaling value of the previous sample's energy
72 | * used in the calculations of the peak detection
73 | * \param influence (float) The influence of the new sample's energy
74 | * in the peak detection algorithm calculations. 1 for total trust
75 | * on the new sample's value in the algorithm, 0 for total trust on
76 | * the moving average calculated by previous samples
77 | * \param discarted_samples (size_t) Number of samples to discard in
78 | * the beginning of execution
79 | */
80 | static sptr make(size_t num_streams, size_t window, float scale, float influence, size_t discarted_samples);
81 | };
82 |
83 | } // namespace devsync
84 | } // namespace gr
85 |
86 | #endif /* INCLUDED_DEVSYNC_PEAK_DETECTOR_H */
87 |
88 |
--------------------------------------------------------------------------------
/cmake/Modules/GrTest.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2010-2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | if(DEFINED __INCLUDED_GR_TEST_CMAKE)
21 | return()
22 | endif()
23 | set(__INCLUDED_GR_TEST_CMAKE TRUE)
24 |
25 | ########################################################################
26 | # Add a unit test and setup the environment for a unit test.
27 | # Takes the same arguments as the ADD_TEST function.
28 | #
29 | # Before calling set the following variables:
30 | # GR_TEST_TARGET_DEPS - built targets for the library path
31 | # GR_TEST_LIBRARY_DIRS - directories for the library path
32 | # GR_TEST_PYTHON_DIRS - directories for the python path
33 | # GR_TEST_ENVIRONS - other environment key/value pairs
34 | ########################################################################
35 | function(GR_ADD_TEST test_name)
36 |
37 | #Ensure that the build exe also appears in the PATH.
38 | list(APPEND GR_TEST_TARGET_DEPS ${ARGN})
39 |
40 | #In the land of windows, all libraries must be in the PATH.
41 | #Since the dependent libraries are not yet installed,
42 | #we must manually set them in the PATH to run tests.
43 | #The following appends the path of a target dependency.
44 | foreach(target ${GR_TEST_TARGET_DEPS})
45 | get_target_property(location ${target} LOCATION)
46 | if(location)
47 | get_filename_component(path ${location} PATH)
48 | string(REGEX REPLACE "\\$\\(.*\\)" ${CMAKE_BUILD_TYPE} path ${path})
49 | list(APPEND GR_TEST_LIBRARY_DIRS ${path})
50 | endif(location)
51 | endforeach(target)
52 |
53 | if(WIN32)
54 | #SWIG generates the python library files into a subdirectory.
55 | #Therefore, we must append this subdirectory into PYTHONPATH.
56 | #Only do this for the python directories matching the following:
57 | foreach(pydir ${GR_TEST_PYTHON_DIRS})
58 | get_filename_component(name ${pydir} NAME)
59 | if(name MATCHES "^(swig|lib|src)$")
60 | list(APPEND GR_TEST_PYTHON_DIRS ${pydir}/${CMAKE_BUILD_TYPE})
61 | endif()
62 | endforeach(pydir)
63 | endif(WIN32)
64 |
65 | file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} srcdir)
66 | file(TO_NATIVE_PATH "${GR_TEST_LIBRARY_DIRS}" libpath) #ok to use on dir list?
67 | file(TO_NATIVE_PATH "${GR_TEST_PYTHON_DIRS}" pypath) #ok to use on dir list?
68 |
69 | set(environs "VOLK_GENERIC=1" "GR_DONT_LOAD_PREFS=1" "srcdir=${srcdir}")
70 | list(APPEND environs ${GR_TEST_ENVIRONS})
71 |
72 | #http://www.cmake.org/pipermail/cmake/2009-May/029464.html
73 | #Replaced this add test + set environs code with the shell script generation.
74 | #Its nicer to be able to manually run the shell script to diagnose problems.
75 | #ADD_TEST(${ARGV})
76 | #SET_TESTS_PROPERTIES(${test_name} PROPERTIES ENVIRONMENT "${environs}")
77 |
78 | if(UNIX)
79 | set(LD_PATH_VAR "LD_LIBRARY_PATH")
80 | if(APPLE)
81 | set(LD_PATH_VAR "DYLD_LIBRARY_PATH")
82 | endif()
83 |
84 | set(binpath "${CMAKE_CURRENT_BINARY_DIR}:$PATH")
85 | list(APPEND libpath "$${LD_PATH_VAR}")
86 | list(APPEND pypath "$PYTHONPATH")
87 |
88 | #replace list separator with the path separator
89 | string(REPLACE ";" ":" libpath "${libpath}")
90 | string(REPLACE ";" ":" pypath "${pypath}")
91 | list(APPEND environs "PATH=${binpath}" "${LD_PATH_VAR}=${libpath}" "PYTHONPATH=${pypath}")
92 |
93 | #generate a bat file that sets the environment and runs the test
94 | if (CMAKE_CROSSCOMPILING)
95 | set(SHELL "/bin/sh")
96 | else(CMAKE_CROSSCOMPILING)
97 | find_program(SHELL sh)
98 | endif(CMAKE_CROSSCOMPILING)
99 | set(sh_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.sh)
100 | file(WRITE ${sh_file} "#!${SHELL}\n")
101 | #each line sets an environment variable
102 | foreach(environ ${environs})
103 | file(APPEND ${sh_file} "export ${environ}\n")
104 | endforeach(environ)
105 | #load the command to run with its arguments
106 | foreach(arg ${ARGN})
107 | file(APPEND ${sh_file} "${arg} ")
108 | endforeach(arg)
109 | file(APPEND ${sh_file} "\n")
110 |
111 | #make the shell file executable
112 | execute_process(COMMAND chmod +x ${sh_file})
113 |
114 | add_test(${test_name} ${SHELL} ${sh_file})
115 |
116 | endif(UNIX)
117 |
118 | if(WIN32)
119 | list(APPEND libpath ${DLL_PATHS} "%PATH%")
120 | list(APPEND pypath "%PYTHONPATH%")
121 |
122 | #replace list separator with the path separator (escaped)
123 | string(REPLACE ";" "\\;" libpath "${libpath}")
124 | string(REPLACE ";" "\\;" pypath "${pypath}")
125 | list(APPEND environs "PATH=${libpath}" "PYTHONPATH=${pypath}")
126 |
127 | #generate a bat file that sets the environment and runs the test
128 | set(bat_file ${CMAKE_CURRENT_BINARY_DIR}/${test_name}_test.bat)
129 | file(WRITE ${bat_file} "@echo off\n")
130 | #each line sets an environment variable
131 | foreach(environ ${environs})
132 | file(APPEND ${bat_file} "SET ${environ}\n")
133 | endforeach(environ)
134 | #load the command to run with its arguments
135 | foreach(arg ${ARGN})
136 | file(APPEND ${bat_file} "${arg} ")
137 | endforeach(arg)
138 | file(APPEND ${bat_file} "\n")
139 |
140 | add_test(${test_name} ${bat_file})
141 | endif(WIN32)
142 |
143 | endfunction(GR_ADD_TEST)
144 |
--------------------------------------------------------------------------------
/cmake/Modules/CMakeParseArgumentsCopy.cmake:
--------------------------------------------------------------------------------
1 | # CMAKE_PARSE_ARGUMENTS( args...)
2 | #
3 | # CMAKE_PARSE_ARGUMENTS() is intended to be used in macros or functions for
4 | # parsing the arguments given to that macro or function.
5 | # It processes the arguments and defines a set of variables which hold the
6 | # values of the respective options.
7 | #
8 | # The argument contains all options for the respective macro,
9 | # i.e. keywords which can be used when calling the macro without any value
10 | # following, like e.g. the OPTIONAL keyword of the install() command.
11 | #
12 | # The argument contains all keywords for this macro
13 | # which are followed by one value, like e.g. DESTINATION keyword of the
14 | # install() command.
15 | #
16 | # The argument contains all keywords for this macro
17 | # which can be followed by more than one value, like e.g. the TARGETS or
18 | # FILES keywords of the install() command.
19 | #
20 | # When done, CMAKE_PARSE_ARGUMENTS() will have defined for each of the
21 | # keywords listed in , and
22 | # a variable composed of the given
23 | # followed by "_" and the name of the respective keyword.
24 | # These variables will then hold the respective value from the argument list.
25 | # For the keywords this will be TRUE or FALSE.
26 | #
27 | # All remaining arguments are collected in a variable
28 | # _UNPARSED_ARGUMENTS, this can be checked afterwards to see whether
29 | # your macro was called with unrecognized parameters.
30 | #
31 | # As an example here a my_install() macro, which takes similar arguments as the
32 | # real install() command:
33 | #
34 | # function(MY_INSTALL)
35 | # set(options OPTIONAL FAST)
36 | # set(oneValueArgs DESTINATION RENAME)
37 | # set(multiValueArgs TARGETS CONFIGURATIONS)
38 | # cmake_parse_arguments(MY_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
39 | # ...
40 | #
41 | # Assume my_install() has been called like this:
42 | # my_install(TARGETS foo bar DESTINATION bin OPTIONAL blub)
43 | #
44 | # After the cmake_parse_arguments() call the macro will have set the following
45 | # variables:
46 | # MY_INSTALL_OPTIONAL = TRUE
47 | # MY_INSTALL_FAST = FALSE (this option was not used when calling my_install()
48 | # MY_INSTALL_DESTINATION = "bin"
49 | # MY_INSTALL_RENAME = "" (was not used)
50 | # MY_INSTALL_TARGETS = "foo;bar"
51 | # MY_INSTALL_CONFIGURATIONS = "" (was not used)
52 | # MY_INSTALL_UNPARSED_ARGUMENTS = "blub" (no value expected after "OPTIONAL"
53 | #
54 | # You can the continue and process these variables.
55 | #
56 | # Keywords terminate lists of values, e.g. if directly after a one_value_keyword
57 | # another recognized keyword follows, this is interpreted as the beginning of
58 | # the new option.
59 | # E.g. my_install(TARGETS foo DESTINATION OPTIONAL) would result in
60 | # MY_INSTALL_DESTINATION set to "OPTIONAL", but MY_INSTALL_DESTINATION would
61 | # be empty and MY_INSTALL_OPTIONAL would be set to TRUE therefor.
62 |
63 | #=============================================================================
64 | # Copyright 2010 Alexander Neundorf
65 | #
66 | # Distributed under the OSI-approved BSD License (the "License");
67 | # see accompanying file Copyright.txt for details.
68 | #
69 | # This software is distributed WITHOUT ANY WARRANTY; without even the
70 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
71 | # See the License for more information.
72 | #=============================================================================
73 | # (To distribute this file outside of CMake, substitute the full
74 | # License text for the above reference.)
75 |
76 |
77 | if(__CMAKE_PARSE_ARGUMENTS_INCLUDED)
78 | return()
79 | endif()
80 | set(__CMAKE_PARSE_ARGUMENTS_INCLUDED TRUE)
81 |
82 |
83 | function(CMAKE_PARSE_ARGUMENTS prefix _optionNames _singleArgNames _multiArgNames)
84 | # first set all result variables to empty/FALSE
85 | foreach(arg_name ${_singleArgNames} ${_multiArgNames})
86 | set(${prefix}_${arg_name})
87 | endforeach(arg_name)
88 |
89 | foreach(option ${_optionNames})
90 | set(${prefix}_${option} FALSE)
91 | endforeach(option)
92 |
93 | set(${prefix}_UNPARSED_ARGUMENTS)
94 |
95 | set(insideValues FALSE)
96 | set(currentArgName)
97 |
98 | # now iterate over all arguments and fill the result variables
99 | foreach(currentArg ${ARGN})
100 | list(FIND _optionNames "${currentArg}" optionIndex) # ... then this marks the end of the arguments belonging to this keyword
101 | list(FIND _singleArgNames "${currentArg}" singleArgIndex) # ... then this marks the end of the arguments belonging to this keyword
102 | list(FIND _multiArgNames "${currentArg}" multiArgIndex) # ... then this marks the end of the arguments belonging to this keyword
103 |
104 | if(${optionIndex} EQUAL -1 AND ${singleArgIndex} EQUAL -1 AND ${multiArgIndex} EQUAL -1)
105 | if(insideValues)
106 | if("${insideValues}" STREQUAL "SINGLE")
107 | set(${prefix}_${currentArgName} ${currentArg})
108 | set(insideValues FALSE)
109 | elseif("${insideValues}" STREQUAL "MULTI")
110 | list(APPEND ${prefix}_${currentArgName} ${currentArg})
111 | endif()
112 | else(insideValues)
113 | list(APPEND ${prefix}_UNPARSED_ARGUMENTS ${currentArg})
114 | endif(insideValues)
115 | else()
116 | if(NOT ${optionIndex} EQUAL -1)
117 | set(${prefix}_${currentArg} TRUE)
118 | set(insideValues FALSE)
119 | elseif(NOT ${singleArgIndex} EQUAL -1)
120 | set(currentArgName ${currentArg})
121 | set(${prefix}_${currentArgName})
122 | set(insideValues "SINGLE")
123 | elseif(NOT ${multiArgIndex} EQUAL -1)
124 | set(currentArgName ${currentArg})
125 | set(${prefix}_${currentArgName})
126 | set(insideValues "MULTI")
127 | endif()
128 | endif()
129 |
130 | endforeach(currentArg)
131 |
132 | # propagate the result variables to the caller:
133 | foreach(arg_name ${_singleArgNames} ${_multiArgNames} ${_optionNames})
134 | set(${prefix}_${arg_name} ${${prefix}_${arg_name}} PARENT_SCOPE)
135 | endforeach(arg_name)
136 | set(${prefix}_UNPARSED_ARGUMENTS ${${prefix}_UNPARSED_ARGUMENTS} PARENT_SCOPE)
137 |
138 | endfunction(CMAKE_PARSE_ARGUMENTS _options _singleArgs _multiArgs)
139 |
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/base.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2010 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 | """
22 | A base class is created.
23 |
24 | Classes based upon this are used to make more user-friendly interfaces
25 | to the doxygen xml docs than the generated classes provide.
26 | """
27 |
28 | import os
29 | import pdb
30 |
31 | from xml.parsers.expat import ExpatError
32 |
33 | from generated import compound
34 |
35 |
36 | class Base(object):
37 |
38 | class Duplicate(StandardError):
39 | pass
40 |
41 | class NoSuchMember(StandardError):
42 | pass
43 |
44 | class ParsingError(StandardError):
45 | pass
46 |
47 | def __init__(self, parse_data, top=None):
48 | self._parsed = False
49 | self._error = False
50 | self._parse_data = parse_data
51 | self._members = []
52 | self._dict_members = {}
53 | self._in_category = {}
54 | self._data = {}
55 | if top is not None:
56 | self._xml_path = top._xml_path
57 | # Set up holder of references
58 | else:
59 | top = self
60 | self._refs = {}
61 | self._xml_path = parse_data
62 | self.top = top
63 |
64 | @classmethod
65 | def from_refid(cls, refid, top=None):
66 | """ Instantiate class from a refid rather than parsing object. """
67 | # First check to see if its already been instantiated.
68 | if top is not None and refid in top._refs:
69 | return top._refs[refid]
70 | # Otherwise create a new instance and set refid.
71 | inst = cls(None, top=top)
72 | inst.refid = refid
73 | inst.add_ref(inst)
74 | return inst
75 |
76 | @classmethod
77 | def from_parse_data(cls, parse_data, top=None):
78 | refid = getattr(parse_data, 'refid', None)
79 | if refid is not None and top is not None and refid in top._refs:
80 | return top._refs[refid]
81 | inst = cls(parse_data, top=top)
82 | if refid is not None:
83 | inst.refid = refid
84 | inst.add_ref(inst)
85 | return inst
86 |
87 | def add_ref(self, obj):
88 | if hasattr(obj, 'refid'):
89 | self.top._refs[obj.refid] = obj
90 |
91 | mem_classes = []
92 |
93 | def get_cls(self, mem):
94 | for cls in self.mem_classes:
95 | if cls.can_parse(mem):
96 | return cls
97 | raise StandardError(("Did not find a class for object '%s'." \
98 | % (mem.get_name())))
99 |
100 | def convert_mem(self, mem):
101 | try:
102 | cls = self.get_cls(mem)
103 | converted = cls.from_parse_data(mem, self.top)
104 | if converted is None:
105 | raise StandardError('No class matched this object.')
106 | self.add_ref(converted)
107 | return converted
108 | except StandardError, e:
109 | print e
110 |
111 | @classmethod
112 | def includes(cls, inst):
113 | return isinstance(inst, cls)
114 |
115 | @classmethod
116 | def can_parse(cls, obj):
117 | return False
118 |
119 | def _parse(self):
120 | self._parsed = True
121 |
122 | def _get_dict_members(self, cat=None):
123 | """
124 | For given category a dictionary is returned mapping member names to
125 | members of that category. For names that are duplicated the name is
126 | mapped to None.
127 | """
128 | self.confirm_no_error()
129 | if cat not in self._dict_members:
130 | new_dict = {}
131 | for mem in self.in_category(cat):
132 | if mem.name() not in new_dict:
133 | new_dict[mem.name()] = mem
134 | else:
135 | new_dict[mem.name()] = self.Duplicate
136 | self._dict_members[cat] = new_dict
137 | return self._dict_members[cat]
138 |
139 | def in_category(self, cat):
140 | self.confirm_no_error()
141 | if cat is None:
142 | return self._members
143 | if cat not in self._in_category:
144 | self._in_category[cat] = [mem for mem in self._members
145 | if cat.includes(mem)]
146 | return self._in_category[cat]
147 |
148 | def get_member(self, name, cat=None):
149 | self.confirm_no_error()
150 | # Check if it's in a namespace or class.
151 | bits = name.split('::')
152 | first = bits[0]
153 | rest = '::'.join(bits[1:])
154 | member = self._get_dict_members(cat).get(first, self.NoSuchMember)
155 | # Raise any errors that are returned.
156 | if member in set([self.NoSuchMember, self.Duplicate]):
157 | raise member()
158 | if rest:
159 | return member.get_member(rest, cat=cat)
160 | return member
161 |
162 | def has_member(self, name, cat=None):
163 | try:
164 | mem = self.get_member(name, cat=cat)
165 | return True
166 | except self.NoSuchMember:
167 | return False
168 |
169 | def data(self):
170 | self.confirm_no_error()
171 | return self._data
172 |
173 | def members(self):
174 | self.confirm_no_error()
175 | return self._members
176 |
177 | def process_memberdefs(self):
178 | mdtss = []
179 | for sec in self._retrieved_data.compounddef.sectiondef:
180 | mdtss += sec.memberdef
181 | # At the moment we lose all information associated with sections.
182 | # Sometimes a memberdef is in several sectiondef.
183 | # We make sure we don't get duplicates here.
184 | uniques = set([])
185 | for mem in mdtss:
186 | converted = self.convert_mem(mem)
187 | pair = (mem.name, mem.__class__)
188 | if pair not in uniques:
189 | uniques.add(pair)
190 | self._members.append(converted)
191 |
192 | def retrieve_data(self):
193 | filename = os.path.join(self._xml_path, self.refid + '.xml')
194 | try:
195 | self._retrieved_data = compound.parse(filename)
196 | except ExpatError:
197 | print('Error in xml in file %s' % filename)
198 | self._error = True
199 | self._retrieved_data = None
200 |
201 | def check_parsed(self):
202 | if not self._parsed:
203 | self._parse()
204 |
205 | def confirm_no_error(self):
206 | self.check_parsed()
207 | if self._error:
208 | raise self.ParsingError()
209 |
210 | def error(self):
211 | self.check_parsed()
212 | return self._error
213 |
214 | def name(self):
215 | # first see if we can do it without processing.
216 | if self._parse_data is not None:
217 | return self._parse_data.name
218 | self.check_parsed()
219 | return self._retrieved_data.compounddef.name
220 |
--------------------------------------------------------------------------------
/python/build_utils.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2004,2009,2012 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 |
22 | """Misc utilities used at build time
23 | """
24 |
25 | import re, os, os.path
26 | from build_utils_codes import *
27 |
28 |
29 | # set srcdir to the directory that contains Makefile.am
30 | try:
31 | srcdir = os.environ['srcdir']
32 | except KeyError, e:
33 | srcdir = "."
34 | srcdir = srcdir + '/'
35 |
36 | # set do_makefile to either true or false dependeing on the environment
37 | try:
38 | if os.environ['do_makefile'] == '0':
39 | do_makefile = False
40 | else:
41 | do_makefile = True
42 | except KeyError, e:
43 | do_makefile = False
44 |
45 | # set do_sources to either true or false dependeing on the environment
46 | try:
47 | if os.environ['do_sources'] == '0':
48 | do_sources = False
49 | else:
50 | do_sources = True
51 | except KeyError, e:
52 | do_sources = True
53 |
54 | name_dict = {}
55 |
56 | def log_output_name (name):
57 | (base, ext) = os.path.splitext (name)
58 | ext = ext[1:] # drop the leading '.'
59 |
60 | entry = name_dict.setdefault (ext, [])
61 | entry.append (name)
62 |
63 | def open_and_log_name (name, dir):
64 | global do_sources
65 | if do_sources:
66 | f = open (name, dir)
67 | else:
68 | f = None
69 | log_output_name (name)
70 | return f
71 |
72 | def expand_template (d, template_filename, extra = ""):
73 | '''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file
74 | '''
75 | global do_sources
76 | output_extension = extract_extension (template_filename)
77 | template = open_src (template_filename, 'r')
78 | output_name = d['NAME'] + extra + '.' + output_extension
79 | log_output_name (output_name)
80 | if do_sources:
81 | output = open (output_name, 'w')
82 | do_substitution (d, template, output)
83 | output.close ()
84 | template.close ()
85 |
86 | def output_glue (dirname):
87 | output_makefile_fragment ()
88 | output_ifile_include (dirname)
89 |
90 | def output_makefile_fragment ():
91 | global do_makefile
92 | if not do_makefile:
93 | return
94 | # overwrite the source, which must be writable; this should have been
95 | # checked for beforehand in the top-level Makefile.gen.gen .
96 | f = open (os.path.join (os.environ.get('gendir', os.environ.get('srcdir', '.')), 'Makefile.gen'), 'w')
97 | f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n')
98 | output_subfrag (f, 'h')
99 | output_subfrag (f, 'i')
100 | output_subfrag (f, 'cc')
101 | f.close ()
102 |
103 | def output_ifile_include (dirname):
104 | global do_sources
105 | if do_sources:
106 | f = open ('%s_generated.i' % (dirname,), 'w')
107 | f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n')
108 | files = name_dict.setdefault ('i', [])
109 | files.sort ()
110 | f.write ('%{\n')
111 | for file in files:
112 | f.write ('#include <%s>\n' % (file[0:-1] + 'h',))
113 | f.write ('%}\n\n')
114 | for file in files:
115 | f.write ('%%include <%s>\n' % (file,))
116 |
117 | def output_subfrag (f, ext):
118 | files = name_dict.setdefault (ext, [])
119 | files.sort ()
120 | f.write ("GENERATED_%s =" % (ext.upper ()))
121 | for file in files:
122 | f.write (" \\\n\t%s" % (file,))
123 | f.write ("\n\n")
124 |
125 | def extract_extension (template_name):
126 | # template name is something like: GrFIRfilterXXX.h.t
127 | # we return everything between the penultimate . and .t
128 | mo = re.search (r'\.([a-z]+)\.t$', template_name)
129 | if not mo:
130 | raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,)
131 | return mo.group (1)
132 |
133 | def open_src (name, mode):
134 | global srcdir
135 | return open (os.path.join (srcdir, name), mode)
136 |
137 | def do_substitution (d, in_file, out_file):
138 | def repl (match_obj):
139 | key = match_obj.group (1)
140 | # print key
141 | return d[key]
142 |
143 | inp = in_file.read ()
144 | out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp)
145 | out_file.write (out)
146 |
147 |
148 |
149 | copyright = '''/* -*- c++ -*- */
150 | /*
151 | * Copyright 2003,2004 Free Software Foundation, Inc.
152 | *
153 | * This file is part of GNU Radio
154 | *
155 | * GNU Radio is free software; you can redistribute it and/or modify
156 | * it under the terms of the GNU General Public License as published by
157 | * the Free Software Foundation; either version 3, or (at your option)
158 | * any later version.
159 | *
160 | * GNU Radio is distributed in the hope that it will be useful,
161 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
162 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
163 | * GNU General Public License for more details.
164 | *
165 | * You should have received a copy of the GNU General Public License
166 | * along with GNU Radio; see the file COPYING. If not, write to
167 | * the Free Software Foundation, Inc., 51 Franklin Street,
168 | * Boston, MA 02110-1301, USA.
169 | */
170 | '''
171 |
172 | def is_complex (code3):
173 | if i_code (code3) == 'c' or o_code (code3) == 'c':
174 | return '1'
175 | else:
176 | return '0'
177 |
178 |
179 | def standard_dict (name, code3, package='gr'):
180 | d = {}
181 | d['NAME'] = name
182 | d['NAME_IMPL'] = name+'_impl'
183 | d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
184 | d['GUARD_NAME_IMPL'] = 'INCLUDED_%s_%s_IMPL_H' % (package.upper(), name.upper())
185 | d['BASE_NAME'] = re.sub ('^' + package + '_', '', name)
186 | d['SPTR_NAME'] = '%s_sptr' % name
187 | d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
188 | d['COPYRIGHT'] = copyright
189 | d['TYPE'] = i_type (code3)
190 | d['I_TYPE'] = i_type (code3)
191 | d['O_TYPE'] = o_type (code3)
192 | d['TAP_TYPE'] = tap_type (code3)
193 | d['IS_COMPLEX'] = is_complex (code3)
194 | return d
195 |
196 |
197 | def standard_dict2 (name, code3, package):
198 | d = {}
199 | d['NAME'] = name
200 | d['BASE_NAME'] = name
201 | d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
202 | d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
203 | d['COPYRIGHT'] = copyright
204 | d['TYPE'] = i_type (code3)
205 | d['I_TYPE'] = i_type (code3)
206 | d['O_TYPE'] = o_type (code3)
207 | d['TAP_TYPE'] = tap_type (code3)
208 | d['IS_COMPLEX'] = is_complex (code3)
209 | return d
210 |
211 | def standard_impl_dict2 (name, code3, package):
212 | d = {}
213 | d['NAME'] = name
214 | d['IMPL_NAME'] = name
215 | d['BASE_NAME'] = name.rstrip("impl").rstrip("_")
216 | d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper())
217 | d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten'
218 | d['COPYRIGHT'] = copyright
219 | d['FIR_TYPE'] = "fir_filter_" + code3
220 | d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c'
221 | d['TYPE'] = i_type (code3)
222 | d['I_TYPE'] = i_type (code3)
223 | d['O_TYPE'] = o_type (code3)
224 | d['TAP_TYPE'] = tap_type (code3)
225 | d['IS_COMPLEX'] = is_complex (code3)
226 | return d
227 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright 2011,2012,2014,2016 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | ########################################################################
21 | # Project setup
22 | ########################################################################
23 | cmake_minimum_required(VERSION 2.6)
24 | project(gr-devsync CXX C)
25 | enable_testing()
26 |
27 | #install to PyBOMBS target prefix if defined
28 | if(DEFINED ENV{PYBOMBS_PREFIX})
29 | #IGNORE set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX})
30 | message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}")
31 | endif()
32 |
33 | #select the release build type by default to get optimization flags
34 | if(NOT CMAKE_BUILD_TYPE)
35 | #IGNORE set(CMAKE_BUILD_TYPE "Release")
36 | message(STATUS "Build type not specified: defaulting to release.")
37 | endif(NOT CMAKE_BUILD_TYPE)
38 | #IGNORE set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
39 |
40 | #make sure our local CMake Modules path comes first
41 | list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules)
42 |
43 | # Set the version information here
44 | set(VERSION_INFO_MAJOR_VERSION 1)
45 | set(VERSION_INFO_API_COMPAT 0)
46 | set(VERSION_INFO_MINOR_VERSION 0)
47 | set(VERSION_INFO_MAINT_VERSION git)
48 |
49 | # Set cmake policies.
50 | # This will suppress developer warnings during the cmake process that can occur
51 | # if a newer cmake version than the minimum is used.
52 |
53 | if(POLICY CMP0026)
54 | cmake_policy(SET CMP0026 OLD)
55 | endif()
56 | if(POLICY CMP0043)
57 | cmake_policy(SET CMP0043 OLD)
58 | endif()
59 | if(POLICY CMP0045)
60 | cmake_policy(SET CMP0045 OLD)
61 | endif()
62 | if(POLICY CMP0046)
63 | cmake_policy(SET CMP0046 OLD)
64 | endif()
65 |
66 | ########################################################################
67 | # Compiler specific setup
68 | ########################################################################
69 | if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32)
70 | #http://gcc.gnu.org/wiki/Visibility
71 | add_definitions(-fvisibility=hidden)
72 | endif()
73 |
74 | ########################################################################
75 | # Find boost
76 | ########################################################################
77 | if(UNIX AND EXISTS "/usr/lib64")
78 | list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix
79 | endif(UNIX AND EXISTS "/usr/lib64")
80 | set(Boost_ADDITIONAL_VERSIONS
81 | "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39"
82 | "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44"
83 | "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49"
84 | "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54"
85 | "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59"
86 | "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64"
87 | "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69"
88 | )
89 | find_package(Boost "1.35" COMPONENTS filesystem system)
90 |
91 | if(NOT Boost_FOUND)
92 | message(FATAL_ERROR "Boost required to compile devsync")
93 | endif()
94 | find_package(Armadillo "1.35" COMPONENTS filesystem system)
95 |
96 | if(NOT Armadillo_FOUND)
97 | message(FATAL_ERROR "Armadillo required to compile devsync")
98 | endif()
99 | ########################################################################
100 | # Install directories
101 | ########################################################################
102 | include(GrPlatform) #define LIB_SUFFIX
103 | set(GR_RUNTIME_DIR bin)
104 | set(GR_LIBRARY_DIR lib${LIB_SUFFIX})
105 | set(GR_INCLUDE_DIR include/devsync)
106 | set(GR_DATA_DIR share)
107 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME})
108 | set(GR_DOC_DIR ${GR_DATA_DIR}/doc)
109 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME})
110 | set(GR_CONF_DIR etc)
111 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d)
112 | set(GR_LIBEXEC_DIR libexec)
113 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME})
114 | set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
115 |
116 | ########################################################################
117 | # On Apple only, set install name and use rpath correctly, if not already set
118 | ########################################################################
119 | if(APPLE)
120 | if(NOT CMAKE_INSTALL_NAME_DIR)
121 | set(CMAKE_INSTALL_NAME_DIR
122 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE
123 | PATH "Library Install Name Destination Directory" FORCE)
124 | endif(NOT CMAKE_INSTALL_NAME_DIR)
125 | if(NOT CMAKE_INSTALL_RPATH)
126 | set(CMAKE_INSTALL_RPATH
127 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE
128 | PATH "Library Install RPath" FORCE)
129 | endif(NOT CMAKE_INSTALL_RPATH)
130 | if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH)
131 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE
132 | BOOL "Do Build Using Library Install RPath" FORCE)
133 | endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH)
134 | endif(APPLE)
135 |
136 | ########################################################################
137 | # Find gnuradio build dependencies
138 | ########################################################################
139 | find_package(CppUnit)
140 | find_package(Doxygen)
141 |
142 | # Search for GNU Radio and its components and versions. Add any
143 | # components required to the list of GR_REQUIRED_COMPONENTS (in all
144 | # caps such as FILTER or FFT) and change the version to the minimum
145 | # API compatible version required.
146 | set(GR_REQUIRED_COMPONENTS RUNTIME)
147 | find_package(Gnuradio "3.7.2" REQUIRED)
148 | list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules)
149 | include(GrVersion)
150 |
151 | if(NOT CPPUNIT_FOUND)
152 | message(FATAL_ERROR "CppUnit required to compile devsync")
153 | endif()
154 |
155 | ########################################################################
156 | # Setup doxygen option
157 | ########################################################################
158 | if(DOXYGEN_FOUND)
159 | option(ENABLE_DOXYGEN "Build docs using Doxygen" ON)
160 | else(DOXYGEN_FOUND)
161 | option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF)
162 | endif(DOXYGEN_FOUND)
163 |
164 | ########################################################################
165 | # Setup the include and linker paths
166 | ########################################################################
167 | include_directories(
168 | ${CMAKE_SOURCE_DIR}/lib
169 | ${CMAKE_SOURCE_DIR}/include
170 | ${CMAKE_BINARY_DIR}/lib
171 | ${CMAKE_BINARY_DIR}/include
172 | ${Boost_INCLUDE_DIRS}
173 | ${CPPUNIT_INCLUDE_DIRS}
174 | ${GNURADIO_ALL_INCLUDE_DIRS}
175 | )
176 |
177 | link_directories(
178 | ${Boost_LIBRARY_DIRS}
179 | ${CPPUNIT_LIBRARY_DIRS}
180 | ${GNURADIO_RUNTIME_LIBRARY_DIRS}
181 | )
182 |
183 | # Set component parameters
184 | set(GR_DEVSYNC_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE)
185 | set(GR_DEVSYNC_SWIG_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/swig CACHE INTERNAL "" FORCE)
186 |
187 | ########################################################################
188 | # Create uninstall target
189 | ########################################################################
190 | configure_file(
191 | ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in
192 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
193 | @ONLY)
194 |
195 | add_custom_target(uninstall
196 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
197 | )
198 |
199 | ########################################################################
200 | # Add subdirectories
201 | ########################################################################
202 | add_subdirectory(include/devsync)
203 | add_subdirectory(lib)
204 | add_subdirectory(swig)
205 | add_subdirectory(python)
206 | add_subdirectory(grc)
207 | add_subdirectory(apps)
208 | add_subdirectory(docs)
209 |
210 | ########################################################################
211 | # Install cmake search helper for this library
212 | ########################################################################
213 | if(NOT CMAKE_MODULES_DIR)
214 | set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake)
215 | endif(NOT CMAKE_MODULES_DIR)
216 |
217 | install(FILES cmake/Modules/devsyncConfig.cmake
218 | DESTINATION ${CMAKE_MODULES_DIR}/devsync
219 | )
220 |
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/doxyindex.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2010 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 | """
22 | Classes providing more user-friendly interfaces to the doxygen xml
23 | docs than the generated classes provide.
24 | """
25 |
26 | import os
27 |
28 | from generated import index
29 | from base import Base
30 | from text import description
31 |
32 | class DoxyIndex(Base):
33 | """
34 | Parses a doxygen xml directory.
35 | """
36 |
37 | __module__ = "gnuradio.utils.doxyxml"
38 |
39 | def _parse(self):
40 | if self._parsed:
41 | return
42 | super(DoxyIndex, self)._parse()
43 | self._root = index.parse(os.path.join(self._xml_path, 'index.xml'))
44 | for mem in self._root.compound:
45 | converted = self.convert_mem(mem)
46 | # For files and namespaces we want the contents to be
47 | # accessible directly from the parent rather than having
48 | # to go through the file object.
49 | if self.get_cls(mem) == DoxyFile:
50 | if mem.name.endswith('.h'):
51 | self._members += converted.members()
52 | self._members.append(converted)
53 | elif self.get_cls(mem) == DoxyNamespace:
54 | self._members += converted.members()
55 | self._members.append(converted)
56 | else:
57 | self._members.append(converted)
58 |
59 |
60 | def generate_swig_doc_i(self):
61 | """
62 | %feature("docstring") gr_make_align_on_samplenumbers_ss::align_state "
63 | Wraps the C++: gr_align_on_samplenumbers_ss::align_state";
64 | """
65 | pass
66 |
67 |
68 | class DoxyCompMem(Base):
69 |
70 |
71 | kind = None
72 |
73 | def __init__(self, *args, **kwargs):
74 | super(DoxyCompMem, self).__init__(*args, **kwargs)
75 |
76 | @classmethod
77 | def can_parse(cls, obj):
78 | return obj.kind == cls.kind
79 |
80 | def set_descriptions(self, parse_data):
81 | bd = description(getattr(parse_data, 'briefdescription', None))
82 | dd = description(getattr(parse_data, 'detaileddescription', None))
83 | self._data['brief_description'] = bd
84 | self._data['detailed_description'] = dd
85 |
86 | def set_parameters(self, data):
87 | vs = [ddc.value for ddc in data.detaileddescription.content_]
88 | pls = []
89 | for v in vs:
90 | if hasattr(v, 'parameterlist'):
91 | pls += v.parameterlist
92 | pis = []
93 | for pl in pls:
94 | pis += pl.parameteritem
95 | dpis = []
96 | for pi in pis:
97 | dpi = DoxyParameterItem(pi)
98 | dpi._parse()
99 | dpis.append(dpi)
100 | self._data['params'] = dpis
101 |
102 |
103 | class DoxyCompound(DoxyCompMem):
104 | pass
105 |
106 | class DoxyMember(DoxyCompMem):
107 | pass
108 |
109 | class DoxyFunction(DoxyMember):
110 |
111 | __module__ = "gnuradio.utils.doxyxml"
112 |
113 | kind = 'function'
114 |
115 | def _parse(self):
116 | if self._parsed:
117 | return
118 | super(DoxyFunction, self)._parse()
119 | self.set_descriptions(self._parse_data)
120 | self.set_parameters(self._parse_data)
121 | if not self._data['params']:
122 | # If the params weren't set by a comment then just grab the names.
123 | self._data['params'] = []
124 | prms = self._parse_data.param
125 | for prm in prms:
126 | self._data['params'].append(DoxyParam(prm))
127 |
128 | brief_description = property(lambda self: self.data()['brief_description'])
129 | detailed_description = property(lambda self: self.data()['detailed_description'])
130 | params = property(lambda self: self.data()['params'])
131 |
132 | Base.mem_classes.append(DoxyFunction)
133 |
134 |
135 | class DoxyParam(DoxyMember):
136 |
137 | __module__ = "gnuradio.utils.doxyxml"
138 |
139 | def _parse(self):
140 | if self._parsed:
141 | return
142 | super(DoxyParam, self)._parse()
143 | self.set_descriptions(self._parse_data)
144 | self._data['declname'] = self._parse_data.declname
145 |
146 | @property
147 | def description(self):
148 | descriptions = []
149 | if self.brief_description:
150 | descriptions.append(self.brief_description)
151 | if self.detailed_description:
152 | descriptions.append(self.detailed_description)
153 | return '\n\n'.join(descriptions)
154 |
155 | brief_description = property(lambda self: self.data()['brief_description'])
156 | detailed_description = property(lambda self: self.data()['detailed_description'])
157 | name = property(lambda self: self.data()['declname'])
158 |
159 | class DoxyParameterItem(DoxyMember):
160 | """A different representation of a parameter in Doxygen."""
161 |
162 | def _parse(self):
163 | if self._parsed:
164 | return
165 | super(DoxyParameterItem, self)._parse()
166 | names = []
167 | for nl in self._parse_data.parameternamelist:
168 | for pn in nl.parametername:
169 | names.append(description(pn))
170 | # Just take first name
171 | self._data['name'] = names[0]
172 | # Get description
173 | pd = description(self._parse_data.get_parameterdescription())
174 | self._data['description'] = pd
175 |
176 | description = property(lambda self: self.data()['description'])
177 | name = property(lambda self: self.data()['name'])
178 |
179 |
180 | class DoxyClass(DoxyCompound):
181 |
182 | __module__ = "gnuradio.utils.doxyxml"
183 |
184 | kind = 'class'
185 |
186 | def _parse(self):
187 | if self._parsed:
188 | return
189 | super(DoxyClass, self)._parse()
190 | self.retrieve_data()
191 | if self._error:
192 | return
193 | self.set_descriptions(self._retrieved_data.compounddef)
194 | self.set_parameters(self._retrieved_data.compounddef)
195 | # Sectiondef.kind tells about whether private or public.
196 | # We just ignore this for now.
197 | self.process_memberdefs()
198 |
199 | brief_description = property(lambda self: self.data()['brief_description'])
200 | detailed_description = property(lambda self: self.data()['detailed_description'])
201 | params = property(lambda self: self.data()['params'])
202 |
203 | Base.mem_classes.append(DoxyClass)
204 |
205 |
206 | class DoxyFile(DoxyCompound):
207 |
208 | __module__ = "gnuradio.utils.doxyxml"
209 |
210 | kind = 'file'
211 |
212 | def _parse(self):
213 | if self._parsed:
214 | return
215 | super(DoxyFile, self)._parse()
216 | self.retrieve_data()
217 | self.set_descriptions(self._retrieved_data.compounddef)
218 | if self._error:
219 | return
220 | self.process_memberdefs()
221 |
222 | brief_description = property(lambda self: self.data()['brief_description'])
223 | detailed_description = property(lambda self: self.data()['detailed_description'])
224 |
225 | Base.mem_classes.append(DoxyFile)
226 |
227 |
228 | class DoxyNamespace(DoxyCompound):
229 |
230 | __module__ = "gnuradio.utils.doxyxml"
231 |
232 | kind = 'namespace'
233 |
234 | def _parse(self):
235 | if self._parsed:
236 | return
237 | super(DoxyNamespace, self)._parse()
238 | self.retrieve_data()
239 | self.set_descriptions(self._retrieved_data.compounddef)
240 | if self._error:
241 | return
242 | self.process_memberdefs()
243 |
244 | Base.mem_classes.append(DoxyNamespace)
245 |
246 |
247 | class DoxyGroup(DoxyCompound):
248 |
249 | __module__ = "gnuradio.utils.doxyxml"
250 |
251 | kind = 'group'
252 |
253 | def _parse(self):
254 | if self._parsed:
255 | return
256 | super(DoxyGroup, self)._parse()
257 | self.retrieve_data()
258 | if self._error:
259 | return
260 | cdef = self._retrieved_data.compounddef
261 | self._data['title'] = description(cdef.title)
262 | # Process inner groups
263 | grps = cdef.innergroup
264 | for grp in grps:
265 | converted = DoxyGroup.from_refid(grp.refid, top=self.top)
266 | self._members.append(converted)
267 | # Process inner classes
268 | klasses = cdef.innerclass
269 | for kls in klasses:
270 | converted = DoxyClass.from_refid(kls.refid, top=self.top)
271 | self._members.append(converted)
272 | # Process normal members
273 | self.process_memberdefs()
274 |
275 | title = property(lambda self: self.data()['title'])
276 |
277 |
278 | Base.mem_classes.append(DoxyGroup)
279 |
280 |
281 | class DoxyFriend(DoxyMember):
282 |
283 | __module__ = "gnuradio.utils.doxyxml"
284 |
285 | kind = 'friend'
286 |
287 | Base.mem_classes.append(DoxyFriend)
288 |
289 |
290 | class DoxyOther(Base):
291 |
292 | __module__ = "gnuradio.utils.doxyxml"
293 |
294 | kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum',
295 | 'dir', 'page', 'signal', 'slot', 'property'])
296 |
297 | @classmethod
298 | def can_parse(cls, obj):
299 | return obj.kind in cls.kinds
300 |
301 | Base.mem_classes.append(DoxyOther)
302 |
--------------------------------------------------------------------------------
/lib/alligner_impl.cc:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifdef HAVE_CONFIG_H
21 | #include "config.h"
22 | #endif
23 |
24 | #include
25 | #include "alligner_impl.h"
26 |
27 | #include
28 | #define MODPI(a) (((a)<-M_PI) ? a+2*M_PI : ((a)>M_PI ? a-2*M_PI : a))
29 |
30 | namespace gr
31 | {
32 | namespace devsync
33 | {
34 |
35 | alligner::sptr
36 | alligner::make (size_t num_streams)
37 | {
38 | return gnuradio::get_initial_sptr (new alligner_impl (num_streams));
39 | }
40 |
41 | alligner_impl::alligner_impl (size_t num_streams) :
42 | gr::sync_block (
43 | "alligner",
44 | gr::io_signature::make (num_streams, num_streams,
45 | sizeof(gr_complex)),
46 | gr::io_signature::make (num_streams, num_streams,
47 | sizeof(gr_complex))),
48 | d_num_streams (num_streams),
49 | d_sample_counter (0),
50 | d_phase_init (pmt::mp ("phase_init")),
51 | ov_state (SYNCING),
52 | d_init_filled_streams (0),
53 | d_num_delayed_streams (0)
54 | {
55 | message_port_register_in (d_phase_init);
56 | d_delayed_samples_buf = NULL;
57 | d_sample_difference = new size_t[num_streams];
58 | d_cyc_buf_next_idx = new size_t[num_streams];
59 | d_filled_buf_rem = new size_t[num_streams];
60 | d_fine_phase_diffs = new double[num_streams];
61 | d_fine_complex_shifts = new std::complex[num_streams];
62 | for (int i = 0; i < num_streams; i++) {
63 | d_sample_difference[i] = 0;
64 | d_cyc_buf_next_idx[i] = 0;
65 | d_filled_buf_rem[i] = 0;
66 | d_fine_phase_diffs[i] = 0;
67 | }
68 | set_msg_handler (
69 | d_phase_init,
70 | boost::bind (&alligner_impl::recv_phase_shifts, this, _1));
71 | }
72 |
73 | alligner_impl::~alligner_impl ()
74 | {
75 | }
76 |
77 | int
78 | alligner_impl::work (int noutput_items,
79 | gr_vector_const_void_star &input_items,
80 | gr_vector_void_star &output_items)
81 | {
82 | const gr_complex *in;
83 | gr_complex *out;
84 | if (ov_state == SYNCING) {
85 | for (int i = 0; i < d_num_streams; i++) {
86 | in = (const gr_complex *) input_items[i];
87 | out = (gr_complex *) output_items[i];
88 | memcpy (out, in, noutput_items * sizeof(gr_complex));
89 | }
90 | return noutput_items;
91 | }
92 | else if (ov_state == NO_PHASE_DIFF) {
93 | for (int i = 0; i < d_num_streams; i++) {
94 | in = (const gr_complex *) input_items[i];
95 | out = (gr_complex *) output_items[i];
96 | memcpy (out, in, noutput_items * sizeof(gr_complex));
97 | }
98 | return noutput_items;
99 | }
100 | if (ov_state == FIRST_BUFFER_FILL) {
101 | initial_buff_fill (input_items, output_items, noutput_items);
102 | if (ov_state == FIRST_BUFFER_FILL) {
103 | return noutput_items;
104 | }
105 | }
106 | if (ov_state == SYNCED) {
107 | delay_samples (input_items, output_items, noutput_items);
108 | return noutput_items;
109 | }
110 | return noutput_items;
111 | }
112 |
113 | void
114 | alligner_impl::recv_phase_shifts (pmt::pmt_t msg)
115 | {
116 | size_t* diffs = (size_t*) pmt::blob_data (pmt::tuple_ref (msg, 1));
117 | memcpy (d_sample_difference, diffs, d_num_streams * sizeof(size_t));
118 | d_ref_stream = pmt::to_uint64 (pmt::tuple_ref (msg, 0));
119 | gr_complex* fine_shifts = (gr_complex*) pmt::blob_data (
120 | pmt::tuple_ref (msg, 2));
121 | float angle;
122 | for (int i = 0; i < d_num_streams; i++) {
123 | angle = std::atan2 (std::imag (fine_shifts[i]),
124 | std::real (fine_shifts[i]));
125 | std::complex c (std::cos (-angle), std::sin (-angle));
126 | d_fine_complex_shifts[i] = c;
127 | if (d_sample_difference[i] != 0) {
128 | ov_state = FIRST_BUFFER_FILL;
129 | }
130 | }
131 | if (ov_state == FIRST_BUFFER_FILL) {
132 | setup_delays ();
133 | }
134 | else {
135 | ov_state = NO_PHASE_DIFF;
136 | }
137 | return;
138 | }
139 |
140 | void
141 | alligner_impl::setup_delays ()
142 | {
143 | d_delayed_samples_buf = (gr_complex**) malloc (
144 | d_num_streams * sizeof(gr_complex*));
145 | size_t temp_diffs[d_num_streams];
146 | memcpy (temp_diffs, d_sample_difference, d_num_streams * sizeof(size_t));
147 | for (int i = 0; i < d_num_streams; i++) {
148 | d_sample_difference[i] = temp_diffs[d_ref_stream] - temp_diffs[i];
149 | d_filled_buf_rem[i] = d_sample_difference[i];
150 | d_delayed_samples_buf[i] = (gr_complex*) malloc (
151 | d_sample_difference[i] * sizeof(gr_complex));
152 | if (d_sample_difference[i] > 0)
153 | d_num_delayed_streams++;
154 | }
155 | ov_state = FIRST_BUFFER_FILL;
156 | return;
157 |
158 | }
159 |
160 | void
161 | alligner_impl::initial_buff_fill (gr_vector_const_void_star &input_items,
162 | gr_vector_void_star &out,
163 | int noutput_items)
164 | {
165 | const gr_complex* in;
166 | for (int i = 0; i < d_num_streams; i++) {
167 | in = (const gr_complex *) input_items[i];
168 | if (d_filled_buf_rem[i] > 0) {
169 | if (noutput_items >= d_filled_buf_rem[i]) {
170 | if (d_cyc_buf_next_idx[i] == 0) {
171 | memcpy (&d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]],
172 | &in[noutput_items - d_filled_buf_rem[i]],
173 | d_filled_buf_rem[i] * sizeof(gr_complex));
174 | }
175 | else {
176 | memcpy (&d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]], in,
177 | d_filled_buf_rem[i] * sizeof(gr_complex));
178 | }
179 | d_init_filled_streams++;
180 | d_cyc_buf_next_idx[i] = 0;
181 | d_filled_buf_rem[i] = 0;
182 | }
183 | else {
184 | memcpy (&d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]], &in[0],
185 | noutput_items * sizeof(gr_complex));
186 | d_cyc_buf_next_idx[i] += noutput_items;
187 | d_filled_buf_rem[i] -= noutput_items;
188 | }
189 | }
190 | }
191 | if (d_init_filled_streams == d_num_delayed_streams) {
192 | ov_state = SYNCED;
193 | }
194 | return;
195 | }
196 |
197 | void
198 | alligner_impl::delay_samples (gr_vector_const_void_star &input_items,
199 | gr_vector_void_star &output_items,
200 | int noutput_items)
201 | {
202 | const gr_complex* in;
203 | gr_complex* out;
204 | size_t num_first_copy = 0;
205 | size_t num_sec_copy = 0;
206 | for (int i = 0; i < d_num_streams; i++) {
207 | in = (const gr_complex *) input_items[i];
208 | out = (gr_complex *) output_items[i];
209 | if (d_sample_difference[i] == 0) {
210 | memcpy (out, in, noutput_items * sizeof(gr_complex));
211 | volk_32fc_s32fc_multiply_32fc (out, out, d_fine_complex_shifts[i],
212 | noutput_items);
213 | continue;
214 | }
215 | size_t len;
216 | if (noutput_items >= d_sample_difference[i]) {
217 | len = d_sample_difference[i];
218 | }
219 | else {
220 | len = noutput_items;
221 | }
222 | if (d_cyc_buf_next_idx[i] + len <= d_sample_difference[i]) {
223 | memcpy (out, &d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]],
224 | len * sizeof(gr_complex));
225 | memcpy (&d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]],
226 | &in[noutput_items - len], len * sizeof(gr_complex));
227 | if (noutput_items > len) {
228 | memcpy (out + len, in, (noutput_items - len) * sizeof(gr_complex));
229 |
230 | }
231 | d_cyc_buf_next_idx[i] = (d_cyc_buf_next_idx[i] + len)
232 | % d_sample_difference[i];
233 | }
234 | else {
235 | num_first_copy = d_sample_difference[i] - d_cyc_buf_next_idx[i];
236 | num_sec_copy = len - num_first_copy;
237 | memcpy (out, &d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]],
238 | num_first_copy * sizeof(gr_complex));
239 | memcpy (out + num_first_copy, d_delayed_samples_buf[i],
240 | num_sec_copy * sizeof(gr_complex));
241 | memcpy (&d_delayed_samples_buf[i][d_cyc_buf_next_idx[i]],
242 | &in[noutput_items - len],
243 | num_first_copy * sizeof(gr_complex));
244 | memcpy (&d_delayed_samples_buf[i][0],
245 | &in[noutput_items - num_sec_copy],
246 | num_sec_copy * sizeof(gr_complex));
247 | d_cyc_buf_next_idx[i] = num_sec_copy % d_sample_difference[i];
248 | if (noutput_items > len) {
249 | memcpy (out + len, in, (noutput_items - len) * sizeof(gr_complex));
250 | }
251 | }
252 | volk_32fc_s32fc_multiply_32fc (out, out, d_fine_complex_shifts[i],
253 | noutput_items);
254 | }
255 | }
256 | } /* namespace devsync */
257 | } /* namespace gr */
258 |
259 |
--------------------------------------------------------------------------------
/cmake/Modules/GrPython.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2010-2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | if(DEFINED __INCLUDED_GR_PYTHON_CMAKE)
21 | return()
22 | endif()
23 | set(__INCLUDED_GR_PYTHON_CMAKE TRUE)
24 |
25 | ########################################################################
26 | # Setup the python interpreter:
27 | # This allows the user to specify a specific interpreter,
28 | # or finds the interpreter via the built-in cmake module.
29 | ########################################################################
30 | #this allows the user to override PYTHON_EXECUTABLE
31 | if(PYTHON_EXECUTABLE)
32 |
33 | set(PYTHONINTERP_FOUND TRUE)
34 |
35 | #otherwise if not set, try to automatically find it
36 | else(PYTHON_EXECUTABLE)
37 |
38 | #use the built-in find script
39 | find_package(PythonInterp 2)
40 |
41 | #and if that fails use the find program routine
42 | if(NOT PYTHONINTERP_FOUND)
43 | find_program(PYTHON_EXECUTABLE NAMES python python2 python2.7 python2.6 python2.5)
44 | if(PYTHON_EXECUTABLE)
45 | set(PYTHONINTERP_FOUND TRUE)
46 | endif(PYTHON_EXECUTABLE)
47 | endif(NOT PYTHONINTERP_FOUND)
48 |
49 | endif(PYTHON_EXECUTABLE)
50 |
51 | if (CMAKE_CROSSCOMPILING)
52 | set(QA_PYTHON_EXECUTABLE "/usr/bin/python")
53 | else (CMAKE_CROSSCOMPILING)
54 | set(QA_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
55 | endif(CMAKE_CROSSCOMPILING)
56 |
57 | #make the path to the executable appear in the cmake gui
58 | set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter")
59 | set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests")
60 |
61 | #make sure we can use -B with python (introduced in 2.6)
62 | if(PYTHON_EXECUTABLE)
63 | execute_process(
64 | COMMAND ${PYTHON_EXECUTABLE} -B -c ""
65 | OUTPUT_QUIET ERROR_QUIET
66 | RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT
67 | )
68 | if(PYTHON_HAS_DASH_B_RESULT EQUAL 0)
69 | set(PYTHON_DASH_B "-B")
70 | endif()
71 | endif(PYTHON_EXECUTABLE)
72 |
73 | ########################################################################
74 | # Check for the existence of a python module:
75 | # - desc a string description of the check
76 | # - mod the name of the module to import
77 | # - cmd an additional command to run
78 | # - have the result variable to set
79 | ########################################################################
80 | macro(GR_PYTHON_CHECK_MODULE desc mod cmd have)
81 | message(STATUS "")
82 | message(STATUS "Python checking for ${desc}")
83 | execute_process(
84 | COMMAND ${PYTHON_EXECUTABLE} -c "
85 | #########################################
86 | try:
87 | import ${mod}
88 | assert ${cmd}
89 | except ImportError, AssertionError: exit(-1)
90 | except: pass
91 | #########################################"
92 | RESULT_VARIABLE ${have}
93 | )
94 | if(${have} EQUAL 0)
95 | message(STATUS "Python checking for ${desc} - found")
96 | set(${have} TRUE)
97 | else(${have} EQUAL 0)
98 | message(STATUS "Python checking for ${desc} - not found")
99 | set(${have} FALSE)
100 | endif(${have} EQUAL 0)
101 | endmacro(GR_PYTHON_CHECK_MODULE)
102 |
103 | ########################################################################
104 | # Sets the python installation directory GR_PYTHON_DIR
105 | ########################################################################
106 | if(NOT DEFINED GR_PYTHON_DIR)
107 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "
108 | from distutils import sysconfig
109 | print sysconfig.get_python_lib(plat_specific=True, prefix='')
110 | " OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE
111 | )
112 | endif()
113 | file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR)
114 |
115 | ########################################################################
116 | # Create an always-built target with a unique name
117 | # Usage: GR_UNIQUE_TARGET( )
118 | ########################################################################
119 | function(GR_UNIQUE_TARGET desc)
120 | file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
121 | execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
122 | unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
123 | print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))"
124 | OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE)
125 | add_custom_target(${_target} ALL DEPENDS ${ARGN})
126 | endfunction(GR_UNIQUE_TARGET)
127 |
128 | ########################################################################
129 | # Install python sources (also builds and installs byte-compiled python)
130 | ########################################################################
131 | function(GR_PYTHON_INSTALL)
132 | include(CMakeParseArgumentsCopy)
133 | CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN})
134 |
135 | ####################################################################
136 | if(GR_PYTHON_INSTALL_FILES)
137 | ####################################################################
138 | install(${ARGN}) #installs regular python files
139 |
140 | #create a list of all generated files
141 | unset(pysrcfiles)
142 | unset(pycfiles)
143 | unset(pyofiles)
144 | foreach(pyfile ${GR_PYTHON_INSTALL_FILES})
145 | get_filename_component(pyfile ${pyfile} ABSOLUTE)
146 | list(APPEND pysrcfiles ${pyfile})
147 |
148 | #determine if this file is in the source or binary directory
149 | file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile})
150 | string(LENGTH "${source_rel_path}" source_rel_path_len)
151 | file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile})
152 | string(LENGTH "${binary_rel_path}" binary_rel_path_len)
153 |
154 | #and set the generated path appropriately
155 | if(${source_rel_path_len} GREATER ${binary_rel_path_len})
156 | set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path})
157 | else()
158 | set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path})
159 | endif()
160 | list(APPEND pycfiles ${pygenfile}c)
161 | list(APPEND pyofiles ${pygenfile}o)
162 |
163 | #ensure generation path exists
164 | get_filename_component(pygen_path ${pygenfile} PATH)
165 | file(MAKE_DIRECTORY ${pygen_path})
166 |
167 | endforeach(pyfile)
168 |
169 | #the command to generate the pyc files
170 | add_custom_command(
171 | DEPENDS ${pysrcfiles} OUTPUT ${pycfiles}
172 | COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles}
173 | )
174 |
175 | #the command to generate the pyo files
176 | add_custom_command(
177 | DEPENDS ${pysrcfiles} OUTPUT ${pyofiles}
178 | COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles}
179 | )
180 |
181 | #create install rule and add generated files to target list
182 | set(python_install_gen_targets ${pycfiles} ${pyofiles})
183 | install(FILES ${python_install_gen_targets}
184 | DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
185 | COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
186 | )
187 |
188 | ####################################################################
189 | elseif(GR_PYTHON_INSTALL_PROGRAMS)
190 | ####################################################################
191 | file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native)
192 |
193 | if (CMAKE_CROSSCOMPILING)
194 | set(pyexe_native "/usr/bin/env python")
195 | endif()
196 |
197 | foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS})
198 | get_filename_component(pyfile_name ${pyfile} NAME)
199 | get_filename_component(pyfile ${pyfile} ABSOLUTE)
200 | string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe")
201 | list(APPEND python_install_gen_targets ${pyexefile})
202 |
203 | get_filename_component(pyexefile_path ${pyexefile} PATH)
204 | file(MAKE_DIRECTORY ${pyexefile_path})
205 |
206 | add_custom_command(
207 | OUTPUT ${pyexefile} DEPENDS ${pyfile}
208 | COMMAND ${PYTHON_EXECUTABLE} -c
209 | "import re; R=re.compile('^\#!.*$\\n',flags=re.MULTILINE); open('${pyexefile}','w').write('\#!${pyexe_native}\\n'+R.sub('',open('${pyfile}','r').read()))"
210 | COMMENT "Shebangin ${pyfile_name}"
211 | VERBATIM
212 | )
213 |
214 | #on windows, python files need an extension to execute
215 | get_filename_component(pyfile_ext ${pyfile} EXT)
216 | if(WIN32 AND NOT pyfile_ext)
217 | set(pyfile_name "${pyfile_name}.py")
218 | endif()
219 |
220 | install(PROGRAMS ${pyexefile} RENAME ${pyfile_name}
221 | DESTINATION ${GR_PYTHON_INSTALL_DESTINATION}
222 | COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
223 | )
224 | endforeach(pyfile)
225 |
226 | endif()
227 |
228 | GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets})
229 |
230 | endfunction(GR_PYTHON_INSTALL)
231 |
232 | ########################################################################
233 | # Write the python helper script that generates byte code files
234 | ########################################################################
235 | file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py "
236 | import sys, py_compile
237 | files = sys.argv[1:]
238 | srcs, gens = files[:len(files)/2], files[len(files)/2:]
239 | for src, gen in zip(srcs, gens):
240 | py_compile.compile(file=src, cfile=gen, doraise=True)
241 | ")
242 |
--------------------------------------------------------------------------------
/examples/top_block.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python2
2 | # -*- coding: utf-8 -*-
3 | ##################################################
4 | # GNU Radio Python Flow Graph
5 | # Title: Top Block
6 | # Generated: Tue Feb 20 15:54:13 2018
7 | ##################################################
8 |
9 | if __name__ == '__main__':
10 | import ctypes
11 | import sys
12 | if sys.platform.startswith('linux'):
13 | try:
14 | x11 = ctypes.cdll.LoadLibrary('libX11.so')
15 | x11.XInitThreads()
16 | except:
17 | print "Warning: failed to XInitThreads()"
18 |
19 | from PyQt4 import Qt
20 | from gnuradio import blocks
21 | from gnuradio import eng_notation
22 | from gnuradio import filter
23 | from gnuradio import gr
24 | from gnuradio.eng_option import eng_option
25 | from gnuradio.filter import firdes
26 | from optparse import OptionParser
27 | import cmath
28 | import devsync
29 | import numpy
30 | import sys
31 | from gnuradio import qtgui
32 |
33 |
34 | class top_block(gr.top_block, Qt.QWidget):
35 |
36 | def __init__(self):
37 | gr.top_block.__init__(self, "Top Block")
38 | Qt.QWidget.__init__(self)
39 | self.setWindowTitle("Top Block")
40 | qtgui.util.check_set_qss()
41 | try:
42 | self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
43 | except:
44 | pass
45 | self.top_scroll_layout = Qt.QVBoxLayout()
46 | self.setLayout(self.top_scroll_layout)
47 | self.top_scroll = Qt.QScrollArea()
48 | self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
49 | self.top_scroll_layout.addWidget(self.top_scroll)
50 | self.top_scroll.setWidgetResizable(True)
51 | self.top_widget = Qt.QWidget()
52 | self.top_scroll.setWidget(self.top_widget)
53 | self.top_layout = Qt.QVBoxLayout(self.top_widget)
54 | self.top_grid_layout = Qt.QGridLayout()
55 | self.top_layout.addLayout(self.top_grid_layout)
56 |
57 | self.settings = Qt.QSettings("GNU Radio", "top_block")
58 | self.restoreGeometry(self.settings.value("geometry").toByteArray())
59 |
60 |
61 | ##################################################
62 | # Variables
63 | ##################################################
64 | self.samp_rate = samp_rate = 32000
65 | self.num_streams = num_streams = 4
66 | self.num_elements = num_elements = 1024
67 | self.long_seq = long_seq = [ 0.1562 - 0.0j , -0.0051 + 0.1203j, 0.0397 + 0.1112j, 0.0968 - 0.0828j,
68 | 0.0211 - 0.0279j, 0.0598 + 0.0877j, -0.1151 + 0.0552j, -0.0383 + 0.1062j,
69 | 0.0975 + 0.0259j, 0.0533 - 0.0041j, 0.0010 + 0.115j , -0.1368 + 0.0474j,
70 | 0.0245 + 0.0585j, 0.0587 + 0.0149j, -0.0225 - 0.1607j, 0.1192 + 0.0041j,
71 | 0.0625 + 0.0625j, 0.0369 - 0.0983j, -0.0572 - 0.0393j, -0.1313 - 0.0652j,
72 | 0.0822 - 0.0924j, 0.0696 - 0.0141j, -0.0603 - 0.0813j, -0.0565 + 0.0218j,
73 | - 0.0350 + 0.1509j, -0.1219 + 0.0166j, -0.1273 + 0.0205j, 0.0751 + 0.074j ,
74 | - 0.0028 - 0.0538j, -0.0919 - 0.1151j, 0.0917 - 0.1059j, 0.0123 - 0.0976j,
75 | - 0.1562 - 0.0j , 0.0123 + 0.0976j, 0.0917 + 0.1059j, -0.0919 + 0.1151j,
76 | - 0.0028 + 0.0538j, 0.0751 - 0.074j , -0.1273 - 0.0205j, -0.1219 - 0.0166j,
77 | - 0.0350 - 0.1509j, -0.0565 - 0.0218j, -0.0603 + 0.0813j, 0.0696 + 0.0141j,
78 | 0.0822 + 0.0924j, -0.1313 + 0.0652j, -0.0572 + 0.0393j, 0.0369 + 0.0983j,
79 | 0.0625 - 0.0625j, 0.1192 - 0.0041j, -0.0225 + 0.1607j, 0.0587 - 0.0149j,
80 | 0.0245 - 0.0585j, -0.1368 - 0.0474j, 0.0010 - 0.115j , 0.0533 + 0.0041j,
81 | 0.0975 - 0.0259j, -0.0383 - 0.1062j, -0.1151 - 0.0552j, 0.0598 - 0.0877j,
82 | 0.0211 + 0.0279j, 0.0968 + 0.0828j, 0.0397 - 0.1112j, -0.0051 - 0.1203j] + 1000*[0]
83 |
84 | ##################################################
85 | # Blocks
86 | ##################################################
87 | self.fft_filter_xxx_0_4_0_0_0 = filter.fft_filter_ccc(1, (long_seq[::-1]), 1)
88 | self.fft_filter_xxx_0_4_0_0_0.declare_sample_delay(0)
89 | self.fft_filter_xxx_0_4_0_0 = filter.fft_filter_ccc(1, (long_seq[::-1]), 1)
90 | self.fft_filter_xxx_0_4_0_0.declare_sample_delay(0)
91 | self.fft_filter_xxx_0_4_0 = filter.fft_filter_ccc(1, (long_seq[::-1]), 1)
92 | self.fft_filter_xxx_0_4_0.declare_sample_delay(0)
93 | self.fft_filter_xxx_0_4 = filter.fft_filter_ccc(1, (long_seq[::-1]), 1)
94 | self.fft_filter_xxx_0_4.declare_sample_delay(0)
95 | self.devsync_rms_normalization_0 = devsync.rms_normalization(num_streams, num_elements)
96 | self.devsync_peak_detector_0 = devsync.peak_detector(num_streams, 100, 1, 0, 100)
97 | self.devsync_alligner_0 = devsync.alligner(num_streams)
98 | self.blocks_vector_to_stream_1_2 = blocks.vector_to_stream(gr.sizeof_gr_complex*1, num_elements)
99 | self.blocks_vector_to_stream_1_1 = blocks.vector_to_stream(gr.sizeof_gr_complex*1, num_elements)
100 | self.blocks_vector_to_stream_1_0 = blocks.vector_to_stream(gr.sizeof_gr_complex*1, num_elements)
101 | self.blocks_vector_to_stream_1 = blocks.vector_to_stream(gr.sizeof_gr_complex*1, num_elements)
102 | self.blocks_vector_source_x_1 = blocks.vector_source_c(numpy.conj(long_seq) , True, 1, [])
103 | self.blocks_stream_to_vector_0_3_1 = blocks.stream_to_vector(gr.sizeof_gr_complex*1, 1024)
104 | self.blocks_stream_to_vector_0_0_0_1 = blocks.stream_to_vector(gr.sizeof_gr_complex*1, 1024)
105 | self.blocks_stream_to_vector_0_0_0_0_0 = blocks.stream_to_vector(gr.sizeof_gr_complex*1, 1024)
106 | self.blocks_stream_to_vector_0_0 = blocks.stream_to_vector(gr.sizeof_gr_complex*1, 1024)
107 | self.blocks_null_source_0 = blocks.null_source(gr.sizeof_gr_complex*1)
108 | self.blocks_null_sink_1 = blocks.null_sink(gr.sizeof_gr_complex*1)
109 | self.blocks_null_sink_0 = blocks.null_sink(gr.sizeof_gr_complex*1)
110 |
111 |
112 |
113 | ##################################################
114 | # Connections
115 | ##################################################
116 | self.msg_connect((self.devsync_peak_detector_0, 'shifts_out'), (self.devsync_alligner_0, 'phase_init'))
117 | self.connect((self.blocks_null_source_0, 0), (self.devsync_alligner_0, 0))
118 | self.connect((self.blocks_null_source_0, 1), (self.devsync_alligner_0, 1))
119 | self.connect((self.blocks_null_source_0, 2), (self.devsync_alligner_0, 2))
120 | self.connect((self.blocks_null_source_0, 3), (self.devsync_alligner_0, 3))
121 | self.connect((self.blocks_null_source_0, 0), (self.fft_filter_xxx_0_4, 0))
122 | self.connect((self.blocks_null_source_0, 2), (self.fft_filter_xxx_0_4_0, 0))
123 | self.connect((self.blocks_null_source_0, 1), (self.fft_filter_xxx_0_4_0_0, 0))
124 | self.connect((self.blocks_null_source_0, 3), (self.fft_filter_xxx_0_4_0_0_0, 0))
125 | self.connect((self.blocks_stream_to_vector_0_0, 0), (self.devsync_rms_normalization_0, 1))
126 | self.connect((self.blocks_stream_to_vector_0_0_0_0_0, 0), (self.devsync_rms_normalization_0, 3))
127 | self.connect((self.blocks_stream_to_vector_0_0_0_1, 0), (self.devsync_rms_normalization_0, 2))
128 | self.connect((self.blocks_stream_to_vector_0_3_1, 0), (self.devsync_rms_normalization_0, 0))
129 | self.connect((self.blocks_vector_source_x_1, 0), (self.blocks_null_sink_0, 0))
130 | self.connect((self.blocks_vector_to_stream_1, 0), (self.devsync_peak_detector_0, 0))
131 | self.connect((self.blocks_vector_to_stream_1_0, 0), (self.devsync_peak_detector_0, 2))
132 | self.connect((self.blocks_vector_to_stream_1_1, 0), (self.devsync_peak_detector_0, 3))
133 | self.connect((self.blocks_vector_to_stream_1_2, 0), (self.devsync_peak_detector_0, 1))
134 | self.connect((self.devsync_alligner_0, 0), (self.blocks_null_sink_1, 0))
135 | self.connect((self.devsync_alligner_0, 1), (self.blocks_null_sink_1, 1))
136 | self.connect((self.devsync_alligner_0, 2), (self.blocks_null_sink_1, 2))
137 | self.connect((self.devsync_alligner_0, 3), (self.blocks_null_sink_1, 3))
138 | self.connect((self.devsync_rms_normalization_0, 0), (self.blocks_vector_to_stream_1, 0))
139 | self.connect((self.devsync_rms_normalization_0, 2), (self.blocks_vector_to_stream_1_0, 0))
140 | self.connect((self.devsync_rms_normalization_0, 3), (self.blocks_vector_to_stream_1_1, 0))
141 | self.connect((self.devsync_rms_normalization_0, 1), (self.blocks_vector_to_stream_1_2, 0))
142 | self.connect((self.fft_filter_xxx_0_4, 0), (self.blocks_stream_to_vector_0_3_1, 0))
143 | self.connect((self.fft_filter_xxx_0_4_0, 0), (self.blocks_stream_to_vector_0_0_0_1, 0))
144 | self.connect((self.fft_filter_xxx_0_4_0_0, 0), (self.blocks_stream_to_vector_0_0, 0))
145 | self.connect((self.fft_filter_xxx_0_4_0_0_0, 0), (self.blocks_stream_to_vector_0_0_0_0_0, 0))
146 |
147 | def closeEvent(self, event):
148 | self.settings = Qt.QSettings("GNU Radio", "top_block")
149 | self.settings.setValue("geometry", self.saveGeometry())
150 | event.accept()
151 |
152 | def get_samp_rate(self):
153 | return self.samp_rate
154 |
155 | def set_samp_rate(self, samp_rate):
156 | self.samp_rate = samp_rate
157 |
158 | def get_num_streams(self):
159 | return self.num_streams
160 |
161 | def set_num_streams(self, num_streams):
162 | self.num_streams = num_streams
163 |
164 | def get_num_elements(self):
165 | return self.num_elements
166 |
167 | def set_num_elements(self, num_elements):
168 | self.num_elements = num_elements
169 |
170 | def get_long_seq(self):
171 | return self.long_seq
172 |
173 | def set_long_seq(self, long_seq):
174 | self.long_seq = long_seq
175 | self.fft_filter_xxx_0_4_0_0_0.set_taps((self.long_seq[::-1]))
176 | self.fft_filter_xxx_0_4_0_0.set_taps((self.long_seq[::-1]))
177 | self.fft_filter_xxx_0_4_0.set_taps((self.long_seq[::-1]))
178 | self.fft_filter_xxx_0_4.set_taps((self.long_seq[::-1]))
179 | self.blocks_vector_source_x_1.set_data(numpy.conj(self.long_seq) , [])
180 |
181 |
182 | def main(top_block_cls=top_block, options=None):
183 |
184 | from distutils.version import StrictVersion
185 | if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
186 | style = gr.prefs().get_string('qtgui', 'style', 'raster')
187 | Qt.QApplication.setGraphicsSystem(style)
188 | qapp = Qt.QApplication(sys.argv)
189 |
190 | tb = top_block_cls()
191 | tb.start()
192 | tb.show()
193 |
194 | def quitting():
195 | tb.stop()
196 | tb.wait()
197 | qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
198 | qapp.exec_()
199 |
200 |
201 | if __name__ == '__main__':
202 | main()
203 |
--------------------------------------------------------------------------------
/cmake/Modules/GrSwig.cmake:
--------------------------------------------------------------------------------
1 | # Copyright 2010-2011 Free Software Foundation, Inc.
2 | #
3 | # This file is part of GNU Radio
4 | #
5 | # GNU Radio is free software; you can redistribute it and/or modify
6 | # it under the terms of the GNU General Public License as published by
7 | # the Free Software Foundation; either version 3, or (at your option)
8 | # any later version.
9 | #
10 | # GNU Radio is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with GNU Radio; see the file COPYING. If not, write to
17 | # the Free Software Foundation, Inc., 51 Franklin Street,
18 | # Boston, MA 02110-1301, USA.
19 |
20 | if(DEFINED __INCLUDED_GR_SWIG_CMAKE)
21 | return()
22 | endif()
23 | set(__INCLUDED_GR_SWIG_CMAKE TRUE)
24 |
25 | include(GrPython)
26 |
27 | ########################################################################
28 | # Builds a swig documentation file to be generated into python docstrings
29 | # Usage: GR_SWIG_MAKE_DOCS(output_file input_path input_path....)
30 | #
31 | # Set the following variable to specify extra dependent targets:
32 | # - GR_SWIG_DOCS_SOURCE_DEPS
33 | # - GR_SWIG_DOCS_TARGET_DEPS
34 | ########################################################################
35 | function(GR_SWIG_MAKE_DOCS output_file)
36 | if(ENABLE_DOXYGEN)
37 |
38 | #setup the input files variable list, quote formated
39 | set(input_files)
40 | unset(INPUT_PATHS)
41 | foreach(input_path ${ARGN})
42 | if(IS_DIRECTORY ${input_path}) #when input path is a directory
43 | file(GLOB input_path_h_files ${input_path}/*.h)
44 | else() #otherwise its just a file, no glob
45 | set(input_path_h_files ${input_path})
46 | endif()
47 | list(APPEND input_files ${input_path_h_files})
48 | set(INPUT_PATHS "${INPUT_PATHS} \"${input_path}\"")
49 | endforeach(input_path)
50 |
51 | #determine the output directory
52 | get_filename_component(name ${output_file} NAME_WE)
53 | get_filename_component(OUTPUT_DIRECTORY ${output_file} PATH)
54 | set(OUTPUT_DIRECTORY ${OUTPUT_DIRECTORY}/${name}_swig_docs)
55 | make_directory(${OUTPUT_DIRECTORY})
56 |
57 | #generate the Doxyfile used by doxygen
58 | configure_file(
59 | ${CMAKE_SOURCE_DIR}/docs/doxygen/Doxyfile.swig_doc.in
60 | ${OUTPUT_DIRECTORY}/Doxyfile
61 | @ONLY)
62 |
63 | #Create a dummy custom command that depends on other targets
64 | include(GrMiscUtils)
65 | GR_GEN_TARGET_DEPS(_${name}_tag tag_deps ${GR_SWIG_DOCS_TARGET_DEPS})
66 |
67 | #call doxygen on the Doxyfile + input headers
68 | add_custom_command(
69 | OUTPUT ${OUTPUT_DIRECTORY}/xml/index.xml
70 | DEPENDS ${input_files} ${GR_SWIG_DOCS_SOURCE_DEPS} ${tag_deps}
71 | COMMAND ${DOXYGEN_EXECUTABLE} ${OUTPUT_DIRECTORY}/Doxyfile
72 | COMMENT "Generating doxygen xml for ${name} docs"
73 | )
74 |
75 | #call the swig_doc script on the xml files
76 | add_custom_command(
77 | OUTPUT ${output_file}
78 | DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml
79 | COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B}
80 | ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py
81 | ${OUTPUT_DIRECTORY}/xml
82 | ${output_file}
83 | COMMENT "Generating python docstrings for ${name}"
84 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs/doxygen
85 | )
86 |
87 | else(ENABLE_DOXYGEN)
88 | file(WRITE ${output_file} "\n") #no doxygen -> empty file
89 | endif(ENABLE_DOXYGEN)
90 | endfunction(GR_SWIG_MAKE_DOCS)
91 |
92 | ########################################################################
93 | # Build a swig target for the common gnuradio use case. Usage:
94 | # GR_SWIG_MAKE(target ifile ifile ifile...)
95 | #
96 | # Set the following variables before calling:
97 | # - GR_SWIG_FLAGS
98 | # - GR_SWIG_INCLUDE_DIRS
99 | # - GR_SWIG_LIBRARIES
100 | # - GR_SWIG_SOURCE_DEPS
101 | # - GR_SWIG_TARGET_DEPS
102 | # - GR_SWIG_DOC_FILE
103 | # - GR_SWIG_DOC_DIRS
104 | ########################################################################
105 | macro(GR_SWIG_MAKE name)
106 | set(ifiles ${ARGN})
107 |
108 | # Shimming this in here to take care of a SWIG bug with handling
109 | # vector and vector (on 32-bit machines) and
110 | # vector (on 64-bit machines). Use this to test
111 | # the size of size_t, then set SIZE_T_32 if it's a 32-bit machine
112 | # or not if it's 64-bit. The logic in gr_type.i handles the rest.
113 | INCLUDE(CheckTypeSize)
114 | CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
115 | CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
116 | if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
117 | list(APPEND GR_SWIG_FLAGS -DSIZE_T_32)
118 | endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
119 |
120 | #do swig doc generation if specified
121 | if(GR_SWIG_DOC_FILE)
122 | set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS})
123 | list(APPEND GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS})
124 | GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS})
125 | add_custom_target(${name}_swig_doc DEPENDS ${GR_SWIG_DOC_FILE})
126 | list(APPEND GR_SWIG_TARGET_DEPS ${name}_swig_doc ${GR_RUNTIME_SWIG_DOC_FILE})
127 | endif()
128 |
129 | #append additional include directories
130 | find_package(PythonLibs 2)
131 | list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs)
132 | list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS})
133 |
134 | #prepend local swig directories
135 | list(INSERT GR_SWIG_INCLUDE_DIRS 0 ${CMAKE_CURRENT_SOURCE_DIR})
136 | list(INSERT GR_SWIG_INCLUDE_DIRS 0 ${CMAKE_CURRENT_BINARY_DIR})
137 |
138 | #determine include dependencies for swig file
139 | execute_process(
140 | COMMAND ${PYTHON_EXECUTABLE}
141 | ${CMAKE_BINARY_DIR}/get_swig_deps.py
142 | "${ifiles}" "${GR_SWIG_INCLUDE_DIRS}"
143 | OUTPUT_STRIP_TRAILING_WHITESPACE
144 | OUTPUT_VARIABLE SWIG_MODULE_${name}_EXTRA_DEPS
145 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
146 | )
147 |
148 | #Create a dummy custom command that depends on other targets
149 | include(GrMiscUtils)
150 | GR_GEN_TARGET_DEPS(_${name}_swig_tag tag_deps ${GR_SWIG_TARGET_DEPS})
151 | set(tag_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.tag)
152 | add_custom_command(
153 | OUTPUT ${tag_file}
154 | DEPENDS ${GR_SWIG_SOURCE_DEPS} ${tag_deps}
155 | COMMAND ${CMAKE_COMMAND} -E touch ${tag_file}
156 | )
157 |
158 | #append the specified include directories
159 | include_directories(${GR_SWIG_INCLUDE_DIRS})
160 | list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file})
161 |
162 | #setup the swig flags with flags and include directories
163 | set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -module ${name} ${GR_SWIG_FLAGS})
164 | foreach(dir ${GR_SWIG_INCLUDE_DIRS})
165 | list(APPEND CMAKE_SWIG_FLAGS "-I${dir}")
166 | endforeach(dir)
167 |
168 | #set the C++ property on the swig .i file so it builds
169 | set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON)
170 |
171 | #setup the actual swig library target to be built
172 | include(UseSWIG)
173 | SWIG_ADD_MODULE(${name} python ${ifiles})
174 | if(APPLE)
175 | set(PYTHON_LINK_OPTIONS "-undefined dynamic_lookup")
176 | else()
177 | set(PYTHON_LINK_OPTIONS ${PYTHON_LIBRARIES})
178 | endif(APPLE)
179 | SWIG_LINK_LIBRARIES(${name} ${PYTHON_LINK_OPTIONS} ${GR_SWIG_LIBRARIES})
180 | if(${name} STREQUAL "runtime_swig")
181 | SET_TARGET_PROPERTIES(${SWIG_MODULE_runtime_swig_REAL_NAME} PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS")
182 | endif(${name} STREQUAL "runtime_swig")
183 |
184 | endmacro(GR_SWIG_MAKE)
185 |
186 | ########################################################################
187 | # Install swig targets generated by GR_SWIG_MAKE. Usage:
188 | # GR_SWIG_INSTALL(
189 | # TARGETS target target target...
190 | # [DESTINATION destination]
191 | # [COMPONENT component]
192 | # )
193 | ########################################################################
194 | macro(GR_SWIG_INSTALL)
195 |
196 | include(CMakeParseArgumentsCopy)
197 | CMAKE_PARSE_ARGUMENTS(GR_SWIG_INSTALL "" "DESTINATION;COMPONENT" "TARGETS" ${ARGN})
198 |
199 | foreach(name ${GR_SWIG_INSTALL_TARGETS})
200 | install(TARGETS ${SWIG_MODULE_${name}_REAL_NAME}
201 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
202 | COMPONENT ${GR_SWIG_INSTALL_COMPONENT}
203 | )
204 |
205 | include(GrPython)
206 | GR_PYTHON_INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}.py
207 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
208 | COMPONENT ${GR_SWIG_INSTALL_COMPONENT}
209 | )
210 |
211 | GR_LIBTOOL(
212 | TARGET ${SWIG_MODULE_${name}_REAL_NAME}
213 | DESTINATION ${GR_SWIG_INSTALL_DESTINATION}
214 | )
215 |
216 | endforeach(name)
217 |
218 | endmacro(GR_SWIG_INSTALL)
219 |
220 | ########################################################################
221 | # Generate a python file that can determine swig dependencies.
222 | # Used by the make macro above to determine extra dependencies.
223 | # When you build C++, CMake figures out the header dependencies.
224 | # This code essentially performs that logic for swig includes.
225 | ########################################################################
226 | file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py "
227 |
228 | import os, sys, re
229 |
230 | i_include_matcher = re.compile('%(include|import)\\s*[<|\"](.*)[>|\"]')
231 | h_include_matcher = re.compile('#(include)\\s*[<|\"](.*)[>|\"]')
232 | include_dirs = sys.argv[2].split(';')
233 |
234 | def get_swig_incs(file_path):
235 | if file_path.endswith('.i'): matcher = i_include_matcher
236 | else: matcher = h_include_matcher
237 | file_contents = open(file_path, 'r').read()
238 | return matcher.findall(file_contents, re.MULTILINE)
239 |
240 | def get_swig_deps(file_path, level):
241 | deps = [file_path]
242 | if level == 0: return deps
243 | for keyword, inc_file in get_swig_incs(file_path):
244 | for inc_dir in include_dirs:
245 | inc_path = os.path.join(inc_dir, inc_file)
246 | if not os.path.exists(inc_path): continue
247 | deps.extend(get_swig_deps(inc_path, level-1))
248 | break #found, we dont search in lower prio inc dirs
249 | return deps
250 |
251 | if __name__ == '__main__':
252 | ifiles = sys.argv[1].split(';')
253 | deps = sum([get_swig_deps(ifile, 3) for ifile in ifiles], [])
254 | #sys.stderr.write(';'.join(set(deps)) + '\\n\\n')
255 | print(';'.join(set(deps)))
256 | ")
257 |
--------------------------------------------------------------------------------
/lib/peak_detector_impl.cc:
--------------------------------------------------------------------------------
1 | /* -*- c++ -*- */
2 | /*
3 | gr-devsync a phase synchronizer for mutliple SDR devices
4 | Copyright (C) 2018 George Vardakis
5 |
6 | This program is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | */
19 |
20 | #ifdef HAVE_CONFIG_H
21 | #include "config.h"
22 | #endif
23 |
24 | #include
25 | #include "peak_detector_impl.h"
26 | #include
27 | #include
28 | #include
29 | namespace gr
30 | {
31 | namespace devsync
32 | {
33 |
34 | peak_detector::sptr
35 | peak_detector::make (size_t num_streams, size_t window, float scale,
36 | float influence, size_t discarted_samples)
37 | {
38 | return gnuradio::get_initial_sptr (
39 | new peak_detector_impl (num_streams, window, scale, influence,
40 | discarted_samples));
41 | }
42 |
43 | peak_detector_impl::peak_detector_impl (size_t num_streams, size_t window,
44 | float scale, float influence,
45 | size_t discarted_samples) :
46 | gr::sync_block (
47 | "peak_detector",
48 | gr::io_signature::make (num_streams, num_streams,
49 | sizeof(gr_complex)),
50 | gr::io_signature::make (0, 0,0)),
51 | d_num_streams (num_streams),
52 | d_window (window),
53 | d_scale (scale),
54 | d_influence (influence),
55 | d_discarted_samples (discarted_samples),
56 | d_sample_counter (0),
57 | ov_state (WINDOW_FILL),
58 | d_synced_streams (0),
59 | d_ref_stream (0),
60 | d_cyc_buf_next_idx (0),
61 | d_discarted_samples_counter (0),
62 | d_ninput_items (0),
63 | d_noutput_items (0),
64 | d_phase_shifts_out (pmt::mp ("shifts_out"))
65 | {
66 | d_state_vector = new state[num_streams];
67 | d_sample_difference = new size_t[num_streams];
68 | d_zero_counter = new size_t[num_streams];
69 | avgFilter = new float[num_streams];
70 | stdFilter = new float[num_streams];
71 | d_sum = new float[num_streams];
72 | d_sumsqr = new float[num_streams];
73 | d_amp_thres = new float[num_streams];
74 | filteredY.resize (num_streams);
75 | d_max_sample = new gr_complex[num_streams];
76 | d_max_abs_sample = new float[num_streams];
77 | for (int i = 0; i < num_streams; i++) {
78 | d_state_vector[i] = NO_SYNC;
79 | d_sample_difference[i] = 0;
80 | d_max_sample[i] = 0;
81 | d_max_abs_sample[i] = 0;
82 | d_zero_counter[i] = 0;
83 | filteredY[i].resize (d_window);
84 | }
85 | message_port_register_out (d_phase_shifts_out);
86 | LOG_INFO("Discarding initial samples");
87 | }
88 |
89 | peak_detector_impl::~peak_detector_impl ()
90 | {
91 | }
92 |
93 | int
94 | peak_detector_impl::work (int noutput_items,
95 | gr_vector_const_void_star &input_items,
96 | gr_vector_void_star &output_items)
97 | {
98 | const gr_complex *in;
99 | float temp;
100 | d_ninput_items += noutput_items;
101 |
102 | /* At the beginning we discard some samples */
103 | if (d_discarted_samples_counter < d_discarted_samples) {
104 | d_discarted_samples_counter += noutput_items;
105 | d_noutput_items += noutput_items;
106 | return noutput_items;
107 | }
108 | /* Next we estimate the noise floor */
109 | if (ov_state == WINDOW_FILL) {
110 | if (d_sample_counter + noutput_items <= d_window) {
111 | for (int i = 0; i < d_num_streams; i++) {
112 | in = (const gr_complex *) input_items[i];
113 | volk_32fc_magnitude_squared_32f (
114 | filteredY[i].data () + d_sample_counter, in, noutput_items);
115 | }
116 | d_sample_counter += noutput_items;
117 | if (d_sample_counter + noutput_items == d_window) {
118 | ov_state = SYNCING;
119 | d_sample_counter = 0;
120 | mean_std (-1, 0);
121 | d_cyc_buf_next_idx++;
122 | }
123 | d_noutput_items += noutput_items;
124 | return noutput_items;
125 | }
126 | else {
127 | for (int i = 0; i < d_num_streams; i++) {
128 | in = (const gr_complex *) input_items[i];
129 | volk_32fc_magnitude_squared_32f (
130 | filteredY[i].data () + d_sample_counter, in,
131 | (d_window - d_sample_counter));
132 | }
133 | d_sample_counter += (d_window - d_sample_counter);
134 | d_noutput_items += (d_window - d_sample_counter);
135 | ov_state = FIRST_SYNCING;
136 | mean_std (-1, 0);
137 | d_cyc_buf_next_idx++;
138 | LOG_INFO("Transmit the training sequence!");
139 | }
140 | }
141 | if (ov_state == SYNCED) {
142 | d_noutput_items += noutput_items;
143 | return noutput_items;
144 | }
145 | int c;
146 | if (ov_state == FIRST_SYNCING) {
147 | c = (d_window - d_sample_counter);
148 | d_sample_counter = 0;
149 | }
150 | else {
151 | c = 0;
152 | }
153 | size_t prev_index;
154 | if (d_cyc_buf_next_idx == 0) {
155 | prev_index = (d_window - 1);
156 | }
157 | else {
158 | prev_index = (d_cyc_buf_next_idx - 1);
159 | }
160 | for (int i = c; i < noutput_items; i++) {
161 |
162 | if (ov_state == FIRST_SYNC_FOUND) {
163 | d_sample_counter++;
164 | }
165 | else if (ov_state == SYNCED) {
166 | d_noutput_items += (noutput_items - i);
167 | break;
168 | }
169 | d_noutput_items++;
170 | float curr_sample;
171 | for (int stream = 0; stream < d_num_streams; stream++) {
172 | in = (const gr_complex *) input_items[stream];
173 | curr_sample = std::pow (std::real (in[i]), 2)
174 | + std::pow (std::imag (in[i]), 2);
175 | if (d_state_vector[stream] == SYNC) {
176 | continue;
177 | }
178 |
179 | /* The following three conditions will determine the existence
180 | * of a peak */
181 | if ((curr_sample > 0.0001)
182 | && std::abs (curr_sample - avgFilter[stream])
183 | > d_scale * filteredY[stream][prev_index]) {
184 | if (curr_sample > avgFilter[stream]) {
185 | if (curr_sample > d_max_abs_sample[stream]) {
186 | d_max_sample[stream] = in[i];
187 | d_max_abs_sample[stream] = curr_sample;
188 | d_zero_counter[stream] = 0;
189 | }
190 | else {
191 | d_zero_counter[stream]++;
192 | }
193 | }
194 | temp = filteredY[stream][d_cyc_buf_next_idx];
195 | filteredY[stream][d_cyc_buf_next_idx] = d_influence * curr_sample
196 | + (1 - d_influence) * filteredY[stream][prev_index];
197 | mean_std (stream, temp);
198 | }
199 | else {
200 | temp = filteredY[stream][d_cyc_buf_next_idx];
201 | filteredY[stream][d_cyc_buf_next_idx] = curr_sample;
202 | mean_std (stream, temp);
203 | }
204 | if (d_zero_counter[stream] > 100) {
205 | LOG_DEBUG ("Last max for stream %d is %f\n", stream,
206 | d_max_abs_sample[stream]);
207 | d_state_vector[stream] = SYNC;
208 | LOG_INFO("Stream %d synced", stream);
209 | d_synced_streams++;
210 | if (!(ov_state == FIRST_SYNC_FOUND)) {
211 | d_sample_counter = d_zero_counter[stream];
212 | d_sample_difference[stream] = 0;
213 | ov_state = FIRST_SYNC_FOUND;
214 | }
215 | else {
216 | d_sample_difference[stream] = d_sample_counter
217 | - d_zero_counter[stream];
218 | }
219 | if (d_synced_streams == d_num_streams) {
220 | d_ref_stream = stream;
221 | ov_state = SYNCED;
222 | LOG_INFO("All streams synced");
223 | pmt::pmt_t tup = pmt::make_tuple (
224 | pmt::from_uint64 (d_ref_stream),
225 | pmt::make_blob (d_sample_difference,
226 | d_num_streams * sizeof(size_t)),
227 | pmt::make_blob (d_max_sample,
228 | d_num_streams * sizeof(gr_complex)));
229 | message_port_pub (d_phase_shifts_out, tup);
230 | for (int l = 0; l < d_num_streams; l++) {
231 | LOG_INFO("Stream %d, sample offset %d\n", l, d_sample_difference[l]);
232 | }
233 | }
234 | }
235 | if (d_max_abs_sample[stream] > 0) {
236 | if (curr_sample > d_max_abs_sample[stream]) {
237 | d_zero_counter[stream] = 0;
238 | }
239 | else {
240 | d_zero_counter[stream]++;
241 | }
242 | }
243 | d_cyc_buf_next_idx = d_cyc_buf_next_idx % d_window;
244 | }
245 | }
246 | if (ov_state == FIRST_SYNCING)
247 | ov_state = SYNCING;
248 |
249 | return noutput_items;
250 | }
251 | void
252 | peak_detector_impl::mean_std (int stream, float discarded_val)
253 | {
254 | if (stream == -1) {
255 | for (int i = 0; i < d_num_streams; i++) {
256 | if (d_state_vector[i] == NO_SYNC) {
257 | float sum = std::accumulate (std::begin (filteredY[i]),
258 | std::end (filteredY[i]), 0.0);
259 | avgFilter[i] = sum / filteredY[i].size ();
260 | d_sum[i] = sum;
261 |
262 | float accum = 0.0;
263 | std::for_each (std::begin (filteredY[i]), std::end (filteredY[i]),
264 | [&](const float d) {
265 | accum += (d - avgFilter[i]) * (d - avgFilter[i]);
266 | });
267 | stdFilter[i] = sqrt (accum / (filteredY[i].size () - 1));
268 |
269 | std::for_each (std::begin (filteredY[i]), std::end (filteredY[i]),
270 | [&](const float d) {
271 | accum += (d * d);
272 | });
273 | d_sumsqr[i] = accum;
274 | d_amp_thres[i] = avgFilter[i];
275 | }
276 | }
277 | }
278 | else {
279 | if (d_state_vector[stream] == NO_SYNC) {
280 | double mean = 0, M2 = 0, variance = 0;
281 | d_sum[stream] = d_sum[stream] - discarded_val
282 | + filteredY[stream][d_cyc_buf_next_idx];
283 | d_sumsqr[stream] = d_sumsqr[stream] - discarded_val * discarded_val
284 | + filteredY[stream][d_cyc_buf_next_idx]
285 | * filteredY[stream][d_cyc_buf_next_idx];
286 | avgFilter[stream] = d_sum[stream] / d_window;
287 | stdFilter[stream] = std::sqrt (
288 | (d_sumsqr[stream] - 2 * avgFilter[stream] * d_sum[stream]
289 | + d_window * avgFilter[stream] * avgFilter[stream])
290 | / (d_window - 1));
291 |
292 | }
293 | }
294 | }
295 |
296 | } /* namespace devsync */
297 | } /* namespace gr */
298 |
299 |
--------------------------------------------------------------------------------
/cmake/Modules/UseSWIG.cmake:
--------------------------------------------------------------------------------
1 | # - SWIG module for CMake
2 | # Defines the following macros:
3 | # SWIG_ADD_MODULE(name language [ files ])
4 | # - Define swig module with given name and specified language
5 | # SWIG_LINK_LIBRARIES(name [ libraries ])
6 | # - Link libraries to swig module
7 | # All other macros are for internal use only.
8 | # To get the actual name of the swig module,
9 | # use: ${SWIG_MODULE_${name}_REAL_NAME}.
10 | # Set Source files properties such as CPLUSPLUS and SWIG_FLAGS to specify
11 | # special behavior of SWIG. Also global CMAKE_SWIG_FLAGS can be used to add
12 | # special flags to all swig calls.
13 | # Another special variable is CMAKE_SWIG_OUTDIR, it allows one to specify
14 | # where to write all the swig generated module (swig -outdir option)
15 | # The name-specific variable SWIG_MODULE__EXTRA_DEPS may be used
16 | # to specify extra dependencies for the generated modules.
17 | # If the source file generated by swig need some special flag you can use
18 | # set_source_files_properties( ${swig_generated_file_fullname}
19 | # PROPERTIES COMPILE_FLAGS "-bla")
20 |
21 |
22 | #=============================================================================
23 | # Copyright 2004-2009 Kitware, Inc.
24 | # Copyright 2009 Mathieu Malaterre
25 | #
26 | # Distributed under the OSI-approved BSD License (the "License");
27 | # see accompanying file Copyright.txt for details.
28 | #
29 | # This software is distributed WITHOUT ANY WARRANTY; without even the
30 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
31 | # See the License for more information.
32 | #=============================================================================
33 | # (To distribute this file outside of CMake, substitute the full
34 | # License text for the above reference.)
35 |
36 | set(SWIG_CXX_EXTENSION "cxx")
37 | set(SWIG_EXTRA_LIBRARIES "")
38 |
39 | set(SWIG_PYTHON_EXTRA_FILE_EXTENSION "py")
40 |
41 | #
42 | # For given swig module initialize variables associated with it
43 | #
44 | macro(SWIG_MODULE_INITIALIZE name language)
45 | string(TOUPPER "${language}" swig_uppercase_language)
46 | string(TOLOWER "${language}" swig_lowercase_language)
47 | set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}")
48 | set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}")
49 |
50 | set(SWIG_MODULE_${name}_REAL_NAME "${name}")
51 | if("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "UNKNOWN")
52 | message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
53 | elseif("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "PYTHON")
54 | # when swig is used without the -interface it will produce in the module.py
55 | # a 'import _modulename' statement, which implies having a corresponding
56 | # _modulename.so (*NIX), _modulename.pyd (Win32).
57 | set(SWIG_MODULE_${name}_REAL_NAME "_${name}")
58 | elseif("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "PERL")
59 | set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
60 | endif()
61 | endmacro()
62 |
63 | #
64 | # For a given language, input file, and output file, determine extra files that
65 | # will be generated. This is internal swig macro.
66 | #
67 |
68 | macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
69 | set(${outfiles} "")
70 | get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename
71 | ${infile} SWIG_MODULE_NAME)
72 | if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND")
73 | get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${infile}" NAME_WE)
74 | endif()
75 | foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSION})
76 | set(${outfiles} ${${outfiles}}
77 | "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}.${it}")
78 | endforeach()
79 | endmacro()
80 |
81 | #
82 | # Take swig (*.i) file and add proper custom commands for it
83 | #
84 | macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
85 | set(swig_full_infile ${infile})
86 | get_filename_component(swig_source_file_path "${infile}" PATH)
87 | get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
88 | get_source_file_property(swig_source_file_generated ${infile} GENERATED)
89 | get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS)
90 | get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS)
91 | if("${swig_source_file_flags}" STREQUAL "NOTFOUND")
92 | set(swig_source_file_flags "")
93 | endif()
94 | set(swig_source_file_fullname "${infile}")
95 | if(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_SOURCE_DIR}")
96 | string(REGEX REPLACE
97 | "^${CMAKE_CURRENT_SOURCE_DIR}" ""
98 | swig_source_file_relative_path
99 | "${swig_source_file_path}")
100 | else()
101 | if(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_BINARY_DIR}")
102 | string(REGEX REPLACE
103 | "^${CMAKE_CURRENT_BINARY_DIR}" ""
104 | swig_source_file_relative_path
105 | "${swig_source_file_path}")
106 | set(swig_source_file_generated 1)
107 | else()
108 | set(swig_source_file_relative_path "${swig_source_file_path}")
109 | if(swig_source_file_generated)
110 | set(swig_source_file_fullname "${CMAKE_CURRENT_BINARY_DIR}/${infile}")
111 | else()
112 | set(swig_source_file_fullname "${CMAKE_CURRENT_SOURCE_DIR}/${infile}")
113 | endif()
114 | endif()
115 | endif()
116 |
117 | set(swig_generated_file_fullname
118 | "${CMAKE_CURRENT_BINARY_DIR}")
119 | if(swig_source_file_relative_path)
120 | set(swig_generated_file_fullname
121 | "${swig_generated_file_fullname}/${swig_source_file_relative_path}")
122 | endif()
123 | # If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
124 | if(CMAKE_SWIG_OUTDIR)
125 | set(swig_outdir ${CMAKE_SWIG_OUTDIR})
126 | else()
127 | set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR})
128 | endif()
129 | SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
130 | swig_extra_generated_files
131 | "${swig_outdir}"
132 | "${infile}")
133 | set(swig_generated_file_fullname
134 | "${swig_generated_file_fullname}/${swig_source_file_name_we}")
135 | # add the language into the name of the file (i.e. TCL_wrap)
136 | # this allows for the same .i file to be wrapped into different languages
137 | set(swig_generated_file_fullname
138 | "${swig_generated_file_fullname}${SWIG_MODULE_${name}_LANGUAGE}_wrap")
139 |
140 | if(swig_source_file_cplusplus)
141 | set(swig_generated_file_fullname
142 | "${swig_generated_file_fullname}.${SWIG_CXX_EXTENSION}")
143 | else()
144 | set(swig_generated_file_fullname
145 | "${swig_generated_file_fullname}.c")
146 | endif()
147 |
148 | # Shut up some warnings from poor SWIG code generation that we
149 | # can do nothing about, when this flag is available
150 | include(CheckCXXCompilerFlag)
151 | check_cxx_compiler_flag("-Wno-unused-but-set-variable" HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
152 | if(HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
153 | set_source_files_properties(${swig_generated_file_fullname}
154 | PROPERTIES COMPILE_FLAGS "-Wno-unused-but-set-variable")
155 | endif(HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
156 |
157 | get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
158 | set(swig_include_dirs)
159 | foreach(it ${cmake_include_directories})
160 | set(swig_include_dirs ${swig_include_dirs} "-I${it}")
161 | endforeach()
162 |
163 | set(swig_special_flags)
164 | # default is c, so add c++ flag if it is c++
165 | if(swig_source_file_cplusplus)
166 | set(swig_special_flags ${swig_special_flags} "-c++")
167 | endif()
168 | set(swig_extra_flags)
169 | if(SWIG_MODULE_${name}_EXTRA_FLAGS)
170 | set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
171 | endif()
172 |
173 | # hack to work around CMake bug in add_custom_command with multiple OUTPUT files
174 |
175 | file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
176 | execute_process(
177 | COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
178 | unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
179 | print(re.sub('\\W', '_', '${name} ${reldir} ' + unique))"
180 | OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE
181 | )
182 |
183 | file(
184 | WRITE ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp.in
185 | "int main(void){return 0;}\n"
186 | )
187 |
188 | # create dummy dependencies
189 | add_custom_command(
190 | OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp
191 | COMMAND ${CMAKE_COMMAND} -E copy
192 | ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp.in
193 | ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp
194 | DEPENDS "${swig_source_file_fullname}" ${SWIG_MODULE_${name}_EXTRA_DEPS}
195 | COMMENT ""
196 | )
197 |
198 | # create the dummy target
199 | add_executable(${_target} ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp)
200 |
201 | # add a custom command to the dummy target
202 | add_custom_command(
203 | TARGET ${_target}
204 | # Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
205 | COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
206 | COMMAND "${SWIG_EXECUTABLE}"
207 | ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
208 | ${swig_source_file_flags}
209 | ${CMAKE_SWIG_FLAGS}
210 | -outdir ${swig_outdir}
211 | ${swig_special_flags}
212 | ${swig_extra_flags}
213 | ${swig_include_dirs}
214 | -o "${swig_generated_file_fullname}"
215 | "${swig_source_file_fullname}"
216 | COMMENT "Swig source"
217 | )
218 |
219 | #add dummy independent dependencies from the _target to each file
220 | #that will be generated by the SWIG command above
221 |
222 | set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
223 |
224 | foreach(swig_gen_file ${${outfiles}})
225 | add_custom_command(
226 | OUTPUT ${swig_gen_file}
227 | COMMAND ""
228 | DEPENDS ${_target}
229 | COMMENT ""
230 | )
231 | endforeach()
232 |
233 | set_source_files_properties(
234 | ${outfiles} PROPERTIES GENERATED 1
235 | )
236 |
237 | endmacro()
238 |
239 | #
240 | # Create Swig module
241 | #
242 | macro(SWIG_ADD_MODULE name language)
243 | SWIG_MODULE_INITIALIZE(${name} ${language})
244 | set(swig_dot_i_sources)
245 | set(swig_other_sources)
246 | foreach(it ${ARGN})
247 | if(${it} MATCHES ".*\\.i$")
248 | set(swig_dot_i_sources ${swig_dot_i_sources} "${it}")
249 | else()
250 | set(swig_other_sources ${swig_other_sources} "${it}")
251 | endif()
252 | endforeach()
253 |
254 | set(swig_generated_sources)
255 | foreach(it ${swig_dot_i_sources})
256 | SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it})
257 | set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}")
258 | endforeach()
259 | get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
260 | set_directory_properties(PROPERTIES
261 | ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}")
262 | add_library(${SWIG_MODULE_${name}_REAL_NAME}
263 | MODULE
264 | ${swig_generated_sources}
265 | ${swig_other_sources})
266 | string(TOLOWER "${language}" swig_lowercase_language)
267 | if ("${swig_lowercase_language}" STREQUAL "java")
268 | if (APPLE)
269 | # In java you want:
270 | # System.loadLibrary("LIBRARY");
271 | # then JNI will look for a library whose name is platform dependent, namely
272 | # MacOS : libLIBRARY.jnilib
273 | # Windows: LIBRARY.dll
274 | # Linux : libLIBRARY.so
275 | set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib")
276 | endif ()
277 | endif ()
278 | if ("${swig_lowercase_language}" STREQUAL "python")
279 | # this is only needed for the python case where a _modulename.so is generated
280 | set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
281 | # Python extension modules on Windows must have the extension ".pyd"
282 | # instead of ".dll" as of Python 2.5. Older python versions do support
283 | # this suffix.
284 | # http://docs.python.org/whatsnew/ports.html#SECTION0001510000000000000000
285 | #
286 | # Windows: .dll is no longer supported as a filename extension for extension modules.
287 | # .pyd is now the only filename extension that will be searched for.
288 | #
289 | if(WIN32 AND NOT CYGWIN)
290 | set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd")
291 | endif()
292 | endif ()
293 | endmacro()
294 |
295 | #
296 | # Like TARGET_LINK_LIBRARIES but for swig modules
297 | #
298 | macro(SWIG_LINK_LIBRARIES name)
299 | if(SWIG_MODULE_${name}_REAL_NAME)
300 | target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
301 | else()
302 | message(SEND_ERROR "Cannot find Swig library \"${name}\".")
303 | endif()
304 | endmacro()
305 |
--------------------------------------------------------------------------------
/docs/doxygen/swig_doc.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2010-2012 Free Software Foundation, Inc.
3 | #
4 | # This file is part of GNU Radio
5 | #
6 | # GNU Radio is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 3, or (at your option)
9 | # any later version.
10 | #
11 | # GNU Radio is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License
17 | # along with GNU Radio; see the file COPYING. If not, write to
18 | # the Free Software Foundation, Inc., 51 Franklin Street,
19 | # Boston, MA 02110-1301, USA.
20 | #
21 | """
22 | Creates the swig_doc.i SWIG interface file.
23 | Execute using: python swig_doc.py xml_path outputfilename
24 |
25 | The file instructs SWIG to transfer the doxygen comments into the
26 | python docstrings.
27 |
28 | """
29 |
30 | import sys, time
31 |
32 | from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile
33 | from doxyxml import DoxyOther, base
34 |
35 | def py_name(name):
36 | bits = name.split('_')
37 | return '_'.join(bits[1:])
38 |
39 | def make_name(name):
40 | bits = name.split('_')
41 | return bits[0] + '_make_' + '_'.join(bits[1:])
42 |
43 |
44 | class Block(object):
45 | """
46 | Checks if doxyxml produced objects correspond to a gnuradio block.
47 | """
48 |
49 | @classmethod
50 | def includes(cls, item):
51 | if not isinstance(item, DoxyClass):
52 | return False
53 | # Check for a parsing error.
54 | if item.error():
55 | return False
56 | friendname = make_name(item.name())
57 | is_a_block = item.has_member(friendname, DoxyFriend)
58 | # But now sometimes the make function isn't a friend so check again.
59 | if not is_a_block:
60 | is_a_block = di.has_member(friendname, DoxyFunction)
61 | return is_a_block
62 |
63 | class Block2(object):
64 | """
65 | Checks if doxyxml produced objects correspond to a new style
66 | gnuradio block.
67 | """
68 |
69 | @classmethod
70 | def includes(cls, item):
71 | if not isinstance(item, DoxyClass):
72 | return False
73 | # Check for a parsing error.
74 | if item.error():
75 | return False
76 | is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther)
77 | return is_a_block2
78 |
79 |
80 | def utoascii(text):
81 | """
82 | Convert unicode text into ascii and escape quotes.
83 | """
84 | if text is None:
85 | return ''
86 | out = text.encode('ascii', 'replace')
87 | out = out.replace('"', '\\"')
88 | return out
89 |
90 |
91 | def combine_descriptions(obj):
92 | """
93 | Combines the brief and detailed descriptions of an object together.
94 | """
95 | description = []
96 | bd = obj.brief_description.strip()
97 | dd = obj.detailed_description.strip()
98 | if bd:
99 | description.append(bd)
100 | if dd:
101 | description.append(dd)
102 | return utoascii('\n\n'.join(description)).strip()
103 |
104 | def format_params(parameteritems):
105 | output = ['Args:']
106 | template = ' {0} : {1}'
107 | for pi in parameteritems:
108 | output.append(template.format(pi.name, pi.description))
109 | return '\n'.join(output)
110 |
111 | entry_templ = '%feature("docstring") {name} "{docstring}"'
112 | def make_entry(obj, name=None, templ="{description}", description=None, params=[]):
113 | """
114 | Create a docstring entry for a swig interface file.
115 |
116 | obj - a doxyxml object from which documentation will be extracted.
117 | name - the name of the C object (defaults to obj.name())
118 | templ - an optional template for the docstring containing only one
119 | variable named 'description'.
120 | description - if this optional variable is set then it's value is
121 | used as the description instead of extracting it from obj.
122 | """
123 | if name is None:
124 | name=obj.name()
125 | if "operator " in name:
126 | return ''
127 | if description is None:
128 | description = combine_descriptions(obj)
129 | if params:
130 | description += '\n\n'
131 | description += utoascii(format_params(params))
132 | docstring = templ.format(description=description)
133 | if not docstring:
134 | return ''
135 | return entry_templ.format(
136 | name=name,
137 | docstring=docstring,
138 | )
139 |
140 |
141 | def make_func_entry(func, name=None, description=None, params=None):
142 | """
143 | Create a function docstring entry for a swig interface file.
144 |
145 | func - a doxyxml object from which documentation will be extracted.
146 | name - the name of the C object (defaults to func.name())
147 | description - if this optional variable is set then it's value is
148 | used as the description instead of extracting it from func.
149 | params - a parameter list that overrides using func.params.
150 | """
151 | #if params is None:
152 | # params = func.params
153 | #params = [prm.declname for prm in params]
154 | #if params:
155 | # sig = "Params: (%s)" % ", ".join(params)
156 | #else:
157 | # sig = "Params: (NONE)"
158 | #templ = "{description}\n\n" + sig
159 | #return make_entry(func, name=name, templ=utoascii(templ),
160 | # description=description)
161 | return make_entry(func, name=name, description=description, params=params)
162 |
163 |
164 | def make_class_entry(klass, description=None, ignored_methods=[], params=None):
165 | """
166 | Create a class docstring for a swig interface file.
167 | """
168 | if params is None:
169 | params = klass.params
170 | output = []
171 | output.append(make_entry(klass, description=description, params=params))
172 | for func in klass.in_category(DoxyFunction):
173 | if func.name() not in ignored_methods:
174 | name = klass.name() + '::' + func.name()
175 | output.append(make_func_entry(func, name=name))
176 | return "\n\n".join(output)
177 |
178 |
179 | def make_block_entry(di, block):
180 | """
181 | Create class and function docstrings of a gnuradio block for a
182 | swig interface file.
183 | """
184 | descriptions = []
185 | # Get the documentation associated with the class.
186 | class_desc = combine_descriptions(block)
187 | if class_desc:
188 | descriptions.append(class_desc)
189 | # Get the documentation associated with the make function
190 | make_func = di.get_member(make_name(block.name()), DoxyFunction)
191 | make_func_desc = combine_descriptions(make_func)
192 | if make_func_desc:
193 | descriptions.append(make_func_desc)
194 | # Get the documentation associated with the file
195 | try:
196 | block_file = di.get_member(block.name() + ".h", DoxyFile)
197 | file_desc = combine_descriptions(block_file)
198 | if file_desc:
199 | descriptions.append(file_desc)
200 | except base.Base.NoSuchMember:
201 | # Don't worry if we can't find a matching file.
202 | pass
203 | # And join them all together to make a super duper description.
204 | super_description = "\n\n".join(descriptions)
205 | # Associate the combined description with the class and
206 | # the make function.
207 | output = []
208 | output.append(make_class_entry(block, description=super_description))
209 | output.append(make_func_entry(make_func, description=super_description,
210 | params=block.params))
211 | return "\n\n".join(output)
212 |
213 | def make_block2_entry(di, block):
214 | """
215 | Create class and function docstrings of a new style gnuradio block for a
216 | swig interface file.
217 | """
218 | descriptions = []
219 | # For new style blocks all the relevant documentation should be
220 | # associated with the 'make' method.
221 | class_description = combine_descriptions(block)
222 | make_func = block.get_member('make', DoxyFunction)
223 | make_description = combine_descriptions(make_func)
224 | description = class_description + "\n\nConstructor Specific Documentation:\n\n" + make_description
225 | # Associate the combined description with the class and
226 | # the make function.
227 | output = []
228 | output.append(make_class_entry(
229 | block, description=description,
230 | ignored_methods=['make'], params=make_func.params))
231 | makename = block.name() + '::make'
232 | output.append(make_func_entry(
233 | make_func, name=makename, description=description,
234 | params=make_func.params))
235 | return "\n\n".join(output)
236 |
237 | def make_swig_interface_file(di, swigdocfilename, custom_output=None):
238 |
239 | output = ["""
240 | /*
241 | * This file was automatically generated using swig_doc.py.
242 | *
243 | * Any changes to it will be lost next time it is regenerated.
244 | */
245 | """]
246 |
247 | if custom_output is not None:
248 | output.append(custom_output)
249 |
250 | # Create docstrings for the blocks.
251 | blocks = di.in_category(Block)
252 | blocks2 = di.in_category(Block2)
253 |
254 | make_funcs = set([])
255 | for block in blocks:
256 | try:
257 | make_func = di.get_member(make_name(block.name()), DoxyFunction)
258 | # Don't want to risk writing to output twice.
259 | if make_func.name() not in make_funcs:
260 | make_funcs.add(make_func.name())
261 | output.append(make_block_entry(di, block))
262 | except block.ParsingError:
263 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name()))
264 | raise
265 |
266 | for block in blocks2:
267 | try:
268 | make_func = block.get_member('make', DoxyFunction)
269 | make_func_name = block.name() +'::make'
270 | # Don't want to risk writing to output twice.
271 | if make_func_name not in make_funcs:
272 | make_funcs.add(make_func_name)
273 | output.append(make_block2_entry(di, block))
274 | except block.ParsingError:
275 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name()))
276 | raise
277 |
278 | # Create docstrings for functions
279 | # Don't include the make functions since they have already been dealt with.
280 | funcs = [f for f in di.in_category(DoxyFunction)
281 | if f.name() not in make_funcs and not f.name().startswith('std::')]
282 | for f in funcs:
283 | try:
284 | output.append(make_func_entry(f))
285 | except f.ParsingError:
286 | sys.stderr.write('Parsing error for function {0}\n'.format(f.name()))
287 |
288 | # Create docstrings for classes
289 | block_names = [block.name() for block in blocks]
290 | block_names += [block.name() for block in blocks2]
291 | klasses = [k for k in di.in_category(DoxyClass)
292 | if k.name() not in block_names and not k.name().startswith('std::')]
293 | for k in klasses:
294 | try:
295 | output.append(make_class_entry(k))
296 | except k.ParsingError:
297 | sys.stderr.write('Parsing error for class {0}\n'.format(k.name()))
298 |
299 | # Docstrings are not created for anything that is not a function or a class.
300 | # If this excludes anything important please add it here.
301 |
302 | output = "\n\n".join(output)
303 |
304 | swig_doc = file(swigdocfilename, 'w')
305 | swig_doc.write(output)
306 | swig_doc.close()
307 |
308 | if __name__ == "__main__":
309 | # Parse command line options and set up doxyxml.
310 | err_msg = "Execute using: python swig_doc.py xml_path outputfilename"
311 | if len(sys.argv) != 3:
312 | raise StandardError(err_msg)
313 | xml_path = sys.argv[1]
314 | swigdocfilename = sys.argv[2]
315 | di = DoxyIndex(xml_path)
316 |
317 | # gnuradio.gr.msq_queue.insert_tail and delete_head create errors unless docstrings are defined!
318 | # This is presumably a bug in SWIG.
319 | #msg_q = di.get_member(u'gr_msg_queue', DoxyClass)
320 | #insert_tail = msg_q.get_member(u'insert_tail', DoxyFunction)
321 | #delete_head = msg_q.get_member(u'delete_head', DoxyFunction)
322 | output = []
323 | #output.append(make_func_entry(insert_tail, name='gr_py_msg_queue__insert_tail'))
324 | #output.append(make_func_entry(delete_head, name='gr_py_msg_queue__delete_head'))
325 | custom_output = "\n\n".join(output)
326 |
327 | # Generate the docstrings interface file.
328 | make_swig_interface_file(di, swigdocfilename, custom_output=custom_output)
329 |
--------------------------------------------------------------------------------
/docs/doxygen/doxyxml/generated/indexsuper.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | #
4 | # Generated Thu Jun 11 18:43:54 2009 by generateDS.py.
5 | #
6 |
7 | import sys
8 | import getopt
9 | from string import lower as str_lower
10 | from xml.dom import minidom
11 | from xml.dom import Node
12 |
13 | #
14 | # User methods
15 | #
16 | # Calls to the methods in these classes are generated by generateDS.py.
17 | # You can replace these methods by re-implementing the following class
18 | # in a module named generatedssuper.py.
19 |
20 | try:
21 | from generatedssuper import GeneratedsSuper
22 | except ImportError, exp:
23 |
24 | class GeneratedsSuper:
25 | def format_string(self, input_data, input_name=''):
26 | return input_data
27 | def format_integer(self, input_data, input_name=''):
28 | return '%d' % input_data
29 | def format_float(self, input_data, input_name=''):
30 | return '%f' % input_data
31 | def format_double(self, input_data, input_name=''):
32 | return '%e' % input_data
33 | def format_boolean(self, input_data, input_name=''):
34 | return '%s' % input_data
35 |
36 |
37 | #
38 | # If you have installed IPython you can uncomment and use the following.
39 | # IPython is available from http://ipython.scipy.org/.
40 | #
41 |
42 | ## from IPython.Shell import IPShellEmbed
43 | ## args = ''
44 | ## ipshell = IPShellEmbed(args,
45 | ## banner = 'Dropping into IPython',
46 | ## exit_msg = 'Leaving Interpreter, back to program.')
47 |
48 | # Then use the following line where and when you want to drop into the
49 | # IPython shell:
50 | # ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit')
51 |
52 | #
53 | # Globals
54 | #
55 |
56 | ExternalEncoding = 'ascii'
57 |
58 | #
59 | # Support/utility functions.
60 | #
61 |
62 | def showIndent(outfile, level):
63 | for idx in range(level):
64 | outfile.write(' ')
65 |
66 | def quote_xml(inStr):
67 | s1 = (isinstance(inStr, basestring) and inStr or
68 | '%s' % inStr)
69 | s1 = s1.replace('&', '&')
70 | s1 = s1.replace('<', '<')
71 | s1 = s1.replace('>', '>')
72 | return s1
73 |
74 | def quote_attrib(inStr):
75 | s1 = (isinstance(inStr, basestring) and inStr or
76 | '%s' % inStr)
77 | s1 = s1.replace('&', '&')
78 | s1 = s1.replace('<', '<')
79 | s1 = s1.replace('>', '>')
80 | if '"' in s1:
81 | if "'" in s1:
82 | s1 = '"%s"' % s1.replace('"', """)
83 | else:
84 | s1 = "'%s'" % s1
85 | else:
86 | s1 = '"%s"' % s1
87 | return s1
88 |
89 | def quote_python(inStr):
90 | s1 = inStr
91 | if s1.find("'") == -1:
92 | if s1.find('\n') == -1:
93 | return "'%s'" % s1
94 | else:
95 | return "'''%s'''" % s1
96 | else:
97 | if s1.find('"') != -1:
98 | s1 = s1.replace('"', '\\"')
99 | if s1.find('\n') == -1:
100 | return '"%s"' % s1
101 | else:
102 | return '"""%s"""' % s1
103 |
104 |
105 | class MixedContainer:
106 | # Constants for category:
107 | CategoryNone = 0
108 | CategoryText = 1
109 | CategorySimple = 2
110 | CategoryComplex = 3
111 | # Constants for content_type:
112 | TypeNone = 0
113 | TypeText = 1
114 | TypeString = 2
115 | TypeInteger = 3
116 | TypeFloat = 4
117 | TypeDecimal = 5
118 | TypeDouble = 6
119 | TypeBoolean = 7
120 | def __init__(self, category, content_type, name, value):
121 | self.category = category
122 | self.content_type = content_type
123 | self.name = name
124 | self.value = value
125 | def getCategory(self):
126 | return self.category
127 | def getContenttype(self, content_type):
128 | return self.content_type
129 | def getValue(self):
130 | return self.value
131 | def getName(self):
132 | return self.name
133 | def export(self, outfile, level, name, namespace):
134 | if self.category == MixedContainer.CategoryText:
135 | outfile.write(self.value)
136 | elif self.category == MixedContainer.CategorySimple:
137 | self.exportSimple(outfile, level, name)
138 | else: # category == MixedContainer.CategoryComplex
139 | self.value.export(outfile, level, namespace,name)
140 | def exportSimple(self, outfile, level, name):
141 | if self.content_type == MixedContainer.TypeString:
142 | outfile.write('<%s>%s%s>' % (self.name, self.value, self.name))
143 | elif self.content_type == MixedContainer.TypeInteger or \
144 | self.content_type == MixedContainer.TypeBoolean:
145 | outfile.write('<%s>%d%s>' % (self.name, self.value, self.name))
146 | elif self.content_type == MixedContainer.TypeFloat or \
147 | self.content_type == MixedContainer.TypeDecimal:
148 | outfile.write('<%s>%f%s>' % (self.name, self.value, self.name))
149 | elif self.content_type == MixedContainer.TypeDouble:
150 | outfile.write('<%s>%g%s>' % (self.name, self.value, self.name))
151 | def exportLiteral(self, outfile, level, name):
152 | if self.category == MixedContainer.CategoryText:
153 | showIndent(outfile, level)
154 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \
155 | (self.category, self.content_type, self.name, self.value))
156 | elif self.category == MixedContainer.CategorySimple:
157 | showIndent(outfile, level)
158 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \
159 | (self.category, self.content_type, self.name, self.value))
160 | else: # category == MixedContainer.CategoryComplex
161 | showIndent(outfile, level)
162 | outfile.write('MixedContainer(%d, %d, "%s",\n' % \
163 | (self.category, self.content_type, self.name,))
164 | self.value.exportLiteral(outfile, level + 1)
165 | showIndent(outfile, level)
166 | outfile.write(')\n')
167 |
168 |
169 | class _MemberSpec(object):
170 | def __init__(self, name='', data_type='', container=0):
171 | self.name = name
172 | self.data_type = data_type
173 | self.container = container
174 | def set_name(self, name): self.name = name
175 | def get_name(self): return self.name
176 | def set_data_type(self, data_type): self.data_type = data_type
177 | def get_data_type(self): return self.data_type
178 | def set_container(self, container): self.container = container
179 | def get_container(self): return self.container
180 |
181 |
182 | #
183 | # Data representation classes.
184 | #
185 |
186 | class DoxygenType(GeneratedsSuper):
187 | subclass = None
188 | superclass = None
189 | def __init__(self, version=None, compound=None):
190 | self.version = version
191 | if compound is None:
192 | self.compound = []
193 | else:
194 | self.compound = compound
195 | def factory(*args_, **kwargs_):
196 | if DoxygenType.subclass:
197 | return DoxygenType.subclass(*args_, **kwargs_)
198 | else:
199 | return DoxygenType(*args_, **kwargs_)
200 | factory = staticmethod(factory)
201 | def get_compound(self): return self.compound
202 | def set_compound(self, compound): self.compound = compound
203 | def add_compound(self, value): self.compound.append(value)
204 | def insert_compound(self, index, value): self.compound[index] = value
205 | def get_version(self): return self.version
206 | def set_version(self, version): self.version = version
207 | def export(self, outfile, level, namespace_='', name_='DoxygenType', namespacedef_=''):
208 | showIndent(outfile, level)
209 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, ))
210 | self.exportAttributes(outfile, level, namespace_, name_='DoxygenType')
211 | if self.hasContent_():
212 | outfile.write('>\n')
213 | self.exportChildren(outfile, level + 1, namespace_, name_)
214 | showIndent(outfile, level)
215 | outfile.write('%s%s>\n' % (namespace_, name_))
216 | else:
217 | outfile.write(' />\n')
218 | def exportAttributes(self, outfile, level, namespace_='', name_='DoxygenType'):
219 | outfile.write(' version=%s' % (self.format_string(quote_attrib(self.version).encode(ExternalEncoding), input_name='version'), ))
220 | def exportChildren(self, outfile, level, namespace_='', name_='DoxygenType'):
221 | for compound_ in self.compound:
222 | compound_.export(outfile, level, namespace_, name_='compound')
223 | def hasContent_(self):
224 | if (
225 | self.compound is not None
226 | ):
227 | return True
228 | else:
229 | return False
230 | def exportLiteral(self, outfile, level, name_='DoxygenType'):
231 | level += 1
232 | self.exportLiteralAttributes(outfile, level, name_)
233 | if self.hasContent_():
234 | self.exportLiteralChildren(outfile, level, name_)
235 | def exportLiteralAttributes(self, outfile, level, name_):
236 | if self.version is not None:
237 | showIndent(outfile, level)
238 | outfile.write('version = %s,\n' % (self.version,))
239 | def exportLiteralChildren(self, outfile, level, name_):
240 | showIndent(outfile, level)
241 | outfile.write('compound=[\n')
242 | level += 1
243 | for compound in self.compound:
244 | showIndent(outfile, level)
245 | outfile.write('model_.compound(\n')
246 | compound.exportLiteral(outfile, level, name_='compound')
247 | showIndent(outfile, level)
248 | outfile.write('),\n')
249 | level -= 1
250 | showIndent(outfile, level)
251 | outfile.write('],\n')
252 | def build(self, node_):
253 | attrs = node_.attributes
254 | self.buildAttributes(attrs)
255 | for child_ in node_.childNodes:
256 | nodeName_ = child_.nodeName.split(':')[-1]
257 | self.buildChildren(child_, nodeName_)
258 | def buildAttributes(self, attrs):
259 | if attrs.get('version'):
260 | self.version = attrs.get('version').value
261 | def buildChildren(self, child_, nodeName_):
262 | if child_.nodeType == Node.ELEMENT_NODE and \
263 | nodeName_ == 'compound':
264 | obj_ = CompoundType.factory()
265 | obj_.build(child_)
266 | self.compound.append(obj_)
267 | # end class DoxygenType
268 |
269 |
270 | class CompoundType(GeneratedsSuper):
271 | subclass = None
272 | superclass = None
273 | def __init__(self, kind=None, refid=None, name=None, member=None):
274 | self.kind = kind
275 | self.refid = refid
276 | self.name = name
277 | if member is None:
278 | self.member = []
279 | else:
280 | self.member = member
281 | def factory(*args_, **kwargs_):
282 | if CompoundType.subclass:
283 | return CompoundType.subclass(*args_, **kwargs_)
284 | else:
285 | return CompoundType(*args_, **kwargs_)
286 | factory = staticmethod(factory)
287 | def get_name(self): return self.name
288 | def set_name(self, name): self.name = name
289 | def get_member(self): return self.member
290 | def set_member(self, member): self.member = member
291 | def add_member(self, value): self.member.append(value)
292 | def insert_member(self, index, value): self.member[index] = value
293 | def get_kind(self): return self.kind
294 | def set_kind(self, kind): self.kind = kind
295 | def get_refid(self): return self.refid
296 | def set_refid(self, refid): self.refid = refid
297 | def export(self, outfile, level, namespace_='', name_='CompoundType', namespacedef_=''):
298 | showIndent(outfile, level)
299 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, ))
300 | self.exportAttributes(outfile, level, namespace_, name_='CompoundType')
301 | if self.hasContent_():
302 | outfile.write('>\n')
303 | self.exportChildren(outfile, level + 1, namespace_, name_)
304 | showIndent(outfile, level)
305 | outfile.write('%s%s>\n' % (namespace_, name_))
306 | else:
307 | outfile.write(' />\n')
308 | def exportAttributes(self, outfile, level, namespace_='', name_='CompoundType'):
309 | outfile.write(' kind=%s' % (quote_attrib(self.kind), ))
310 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), ))
311 | def exportChildren(self, outfile, level, namespace_='', name_='CompoundType'):
312 | if self.name is not None:
313 | showIndent(outfile, level)
314 | outfile.write('<%sname>%s%sname>\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_))
315 | for member_ in self.member:
316 | member_.export(outfile, level, namespace_, name_='member')
317 | def hasContent_(self):
318 | if (
319 | self.name is not None or
320 | self.member is not None
321 | ):
322 | return True
323 | else:
324 | return False
325 | def exportLiteral(self, outfile, level, name_='CompoundType'):
326 | level += 1
327 | self.exportLiteralAttributes(outfile, level, name_)
328 | if self.hasContent_():
329 | self.exportLiteralChildren(outfile, level, name_)
330 | def exportLiteralAttributes(self, outfile, level, name_):
331 | if self.kind is not None:
332 | showIndent(outfile, level)
333 | outfile.write('kind = "%s",\n' % (self.kind,))
334 | if self.refid is not None:
335 | showIndent(outfile, level)
336 | outfile.write('refid = %s,\n' % (self.refid,))
337 | def exportLiteralChildren(self, outfile, level, name_):
338 | showIndent(outfile, level)
339 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding))
340 | showIndent(outfile, level)
341 | outfile.write('member=[\n')
342 | level += 1
343 | for member in self.member:
344 | showIndent(outfile, level)
345 | outfile.write('model_.member(\n')
346 | member.exportLiteral(outfile, level, name_='member')
347 | showIndent(outfile, level)
348 | outfile.write('),\n')
349 | level -= 1
350 | showIndent(outfile, level)
351 | outfile.write('],\n')
352 | def build(self, node_):
353 | attrs = node_.attributes
354 | self.buildAttributes(attrs)
355 | for child_ in node_.childNodes:
356 | nodeName_ = child_.nodeName.split(':')[-1]
357 | self.buildChildren(child_, nodeName_)
358 | def buildAttributes(self, attrs):
359 | if attrs.get('kind'):
360 | self.kind = attrs.get('kind').value
361 | if attrs.get('refid'):
362 | self.refid = attrs.get('refid').value
363 | def buildChildren(self, child_, nodeName_):
364 | if child_.nodeType == Node.ELEMENT_NODE and \
365 | nodeName_ == 'name':
366 | name_ = ''
367 | for text__content_ in child_.childNodes:
368 | name_ += text__content_.nodeValue
369 | self.name = name_
370 | elif child_.nodeType == Node.ELEMENT_NODE and \
371 | nodeName_ == 'member':
372 | obj_ = MemberType.factory()
373 | obj_.build(child_)
374 | self.member.append(obj_)
375 | # end class CompoundType
376 |
377 |
378 | class MemberType(GeneratedsSuper):
379 | subclass = None
380 | superclass = None
381 | def __init__(self, kind=None, refid=None, name=None):
382 | self.kind = kind
383 | self.refid = refid
384 | self.name = name
385 | def factory(*args_, **kwargs_):
386 | if MemberType.subclass:
387 | return MemberType.subclass(*args_, **kwargs_)
388 | else:
389 | return MemberType(*args_, **kwargs_)
390 | factory = staticmethod(factory)
391 | def get_name(self): return self.name
392 | def set_name(self, name): self.name = name
393 | def get_kind(self): return self.kind
394 | def set_kind(self, kind): self.kind = kind
395 | def get_refid(self): return self.refid
396 | def set_refid(self, refid): self.refid = refid
397 | def export(self, outfile, level, namespace_='', name_='MemberType', namespacedef_=''):
398 | showIndent(outfile, level)
399 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, ))
400 | self.exportAttributes(outfile, level, namespace_, name_='MemberType')
401 | if self.hasContent_():
402 | outfile.write('>\n')
403 | self.exportChildren(outfile, level + 1, namespace_, name_)
404 | showIndent(outfile, level)
405 | outfile.write('%s%s>\n' % (namespace_, name_))
406 | else:
407 | outfile.write(' />\n')
408 | def exportAttributes(self, outfile, level, namespace_='', name_='MemberType'):
409 | outfile.write(' kind=%s' % (quote_attrib(self.kind), ))
410 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), ))
411 | def exportChildren(self, outfile, level, namespace_='', name_='MemberType'):
412 | if self.name is not None:
413 | showIndent(outfile, level)
414 | outfile.write('<%sname>%s%sname>\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_))
415 | def hasContent_(self):
416 | if (
417 | self.name is not None
418 | ):
419 | return True
420 | else:
421 | return False
422 | def exportLiteral(self, outfile, level, name_='MemberType'):
423 | level += 1
424 | self.exportLiteralAttributes(outfile, level, name_)
425 | if self.hasContent_():
426 | self.exportLiteralChildren(outfile, level, name_)
427 | def exportLiteralAttributes(self, outfile, level, name_):
428 | if self.kind is not None:
429 | showIndent(outfile, level)
430 | outfile.write('kind = "%s",\n' % (self.kind,))
431 | if self.refid is not None:
432 | showIndent(outfile, level)
433 | outfile.write('refid = %s,\n' % (self.refid,))
434 | def exportLiteralChildren(self, outfile, level, name_):
435 | showIndent(outfile, level)
436 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding))
437 | def build(self, node_):
438 | attrs = node_.attributes
439 | self.buildAttributes(attrs)
440 | for child_ in node_.childNodes:
441 | nodeName_ = child_.nodeName.split(':')[-1]
442 | self.buildChildren(child_, nodeName_)
443 | def buildAttributes(self, attrs):
444 | if attrs.get('kind'):
445 | self.kind = attrs.get('kind').value
446 | if attrs.get('refid'):
447 | self.refid = attrs.get('refid').value
448 | def buildChildren(self, child_, nodeName_):
449 | if child_.nodeType == Node.ELEMENT_NODE and \
450 | nodeName_ == 'name':
451 | name_ = ''
452 | for text__content_ in child_.childNodes:
453 | name_ += text__content_.nodeValue
454 | self.name = name_
455 | # end class MemberType
456 |
457 |
458 | USAGE_TEXT = """
459 | Usage: python .py [ -s ]
460 | Options:
461 | -s Use the SAX parser, not the minidom parser.
462 | """
463 |
464 | def usage():
465 | print USAGE_TEXT
466 | sys.exit(1)
467 |
468 |
469 | def parse(inFileName):
470 | doc = minidom.parse(inFileName)
471 | rootNode = doc.documentElement
472 | rootObj = DoxygenType.factory()
473 | rootObj.build(rootNode)
474 | # Enable Python to collect the space used by the DOM.
475 | doc = None
476 | sys.stdout.write('\n')
477 | rootObj.export(sys.stdout, 0, name_="doxygenindex",
478 | namespacedef_='')
479 | return rootObj
480 |
481 |
482 | def parseString(inString):
483 | doc = minidom.parseString(inString)
484 | rootNode = doc.documentElement
485 | rootObj = DoxygenType.factory()
486 | rootObj.build(rootNode)
487 | # Enable Python to collect the space used by the DOM.
488 | doc = None
489 | sys.stdout.write('\n')
490 | rootObj.export(sys.stdout, 0, name_="doxygenindex",
491 | namespacedef_='')
492 | return rootObj
493 |
494 |
495 | def parseLiteral(inFileName):
496 | doc = minidom.parse(inFileName)
497 | rootNode = doc.documentElement
498 | rootObj = DoxygenType.factory()
499 | rootObj.build(rootNode)
500 | # Enable Python to collect the space used by the DOM.
501 | doc = None
502 | sys.stdout.write('from index import *\n\n')
503 | sys.stdout.write('rootObj = doxygenindex(\n')
504 | rootObj.exportLiteral(sys.stdout, 0, name_="doxygenindex")
505 | sys.stdout.write(')\n')
506 | return rootObj
507 |
508 |
509 | def main():
510 | args = sys.argv[1:]
511 | if len(args) == 1:
512 | parse(args[0])
513 | else:
514 | usage()
515 |
516 |
517 |
518 |
519 | if __name__ == '__main__':
520 | main()
521 | #import pdb
522 | #pdb.run('main()')
523 |
524 |
--------------------------------------------------------------------------------