├── .clang-format ├── .conda ├── README.md ├── conda-forge.yml └── recipe │ ├── bld.bat │ ├── build.sh │ ├── conda_build_config.yaml │ ├── meta.yaml │ └── yum_requirements.txt ├── .gitattributes ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── MANIFEST.md ├── MANIFEST.yml ├── README.md ├── apps └── CMakeLists.txt ├── cmake ├── Modules │ ├── CMakeParseArgumentsCopy.cmake │ ├── gnuradio-inspectorConfig.cmake │ └── targetConfig.cmake.in └── cmake_uninstall.cmake.in ├── docs ├── CMakeLists.txt ├── README.inspector └── doxygen │ ├── CMakeLists.txt │ ├── Doxyfile.in │ ├── doxyxml │ ├── __init__.py │ ├── base.py │ ├── doxyindex.py │ ├── generated │ │ ├── __init__.py │ │ ├── compound.py │ │ ├── compoundsuper.py │ │ ├── index.py │ │ └── indexsuper.py │ └── text.py │ ├── other │ ├── doxypy.py │ ├── group_defs.dox │ └── main_page.dox │ ├── pydoc_macros.h │ └── update_pydoc.py ├── examples ├── CMakeLists.txt ├── README ├── live_fm_demod.grc ├── live_signal_detection.grc ├── ofdm_estimation.grc ├── ofdm_sync.grc ├── recorder.grc ├── signal_detection.grc └── signal_separation.grc ├── grc ├── CMakeLists.txt ├── inspector_ofdm_synchronizer_cc.block.yml ├── inspector_ofdm_zkf_c.block.yml ├── inspector_qtgui_inspector_sink_vf.block.yml ├── inspector_signal_detector_cvf.block.yml ├── inspector_signal_extractor_c.block.yml └── inspector_signal_separator_c.block.yml ├── include └── gnuradio │ └── inspector │ ├── CMakeLists.txt │ ├── api.h │ ├── inspector_form.h │ ├── ofdm_bouzegzi_c.h │ ├── ofdm_synchronizer_cc.h │ ├── ofdm_zkf_c.h │ ├── qtgui_inspector_sink_vf.h │ ├── signal_detector_cvf.h │ ├── signal_extractor_c.h │ ├── signal_marker.h │ └── signal_separator_c.h ├── lib ├── CMakeLists.txt ├── inspector_form.cc ├── ofdm_bouzegzi_c_impl.cc ├── ofdm_bouzegzi_c_impl.h ├── ofdm_synchronizer_cc_impl.cc ├── ofdm_synchronizer_cc_impl.h ├── ofdm_zkf_c_impl.cc ├── ofdm_zkf_c_impl.h ├── qtgui_inspector_sink_vf_impl.cc ├── qtgui_inspector_sink_vf_impl.h ├── signal_detector_cvf_impl.cc ├── signal_detector_cvf_impl.h ├── signal_extractor_c_impl.cc ├── signal_extractor_c_impl.h ├── signal_marker.cc ├── signal_separator_c_impl.cc └── signal_separator_c_impl.h └── python └── inspector ├── .gitignore ├── CMakeLists.txt ├── __init__.py ├── bindings ├── CMakeLists.txt ├── README.md ├── bind_oot_file.py ├── docstrings │ ├── README.md │ ├── ofdm_bouzegzi_c_pydoc_template.h │ ├── ofdm_synchronizer_cc_pydoc_template.h │ ├── ofdm_zkf_c_pydoc_template.h │ ├── qtgui_inspector_sink_vf_pydoc_template.h │ ├── signal_detector_cvf_pydoc_template.h │ ├── signal_extractor_c_pydoc_template.h │ └── signal_separator_c_pydoc_template.h ├── header_utils.py ├── ofdm_bouzegzi_c_python.cc ├── ofdm_synchronizer_cc_python.cc ├── ofdm_zkf_c_python.cc ├── python_bindings.cc ├── qtgui_inspector_sink_vf_python.cc ├── signal_detector_cvf_python.cc ├── signal_extractor_c_python.cc └── signal_separator_c_python.cc ├── qa_ofdm_synchronizer_cc.py ├── qa_ofdm_zkf_c.py ├── qa_signal_detector_cvf.py └── qa_signal_separator_c.py /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlinesLeft: true 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: All 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: false 22 | BinPackParameters: false 23 | BreakBeforeBraces: Custom 24 | BraceWrapping: 25 | AfterClass: true 26 | AfterControlStatement: false 27 | AfterEnum: false 28 | AfterFunction: true 29 | AfterNamespace: false 30 | AfterObjCDeclaration: false 31 | AfterStruct: false 32 | AfterUnion: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | BreakBeforeBinaryOperators: None 37 | BreakBeforeTernaryOperators: true 38 | BreakConstructorInitializersBeforeComma: false 39 | BreakAfterJavaFieldAnnotations: false 40 | BreakStringLiterals: true 41 | ColumnLimit: 90 42 | CommentPragmas: '^ IWYU pragma:' 43 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 44 | ConstructorInitializerIndentWidth: 4 45 | ContinuationIndentWidth: 4 46 | Cpp11BracedListStyle: false 47 | DerivePointerAlignment: false 48 | DisableFormat: false 49 | ExperimentalAutoDetectBinPacking: false 50 | ForEachMacros: 51 | - foreach 52 | - Q_FOREACH 53 | - BOOST_FOREACH 54 | IncludeCategories: 55 | - Regex: '^"(gnuradio)/' 56 | Priority: 1 57 | - Regex: '^<(gnuradio)/' 58 | Priority: 2 59 | - Regex: '^<(boost)/' 60 | Priority: 98 61 | - Regex: '^<[a-z]*>$' 62 | Priority: 99 63 | - Regex: '^".*"$' 64 | Priority: 0 65 | - Regex: '.*' 66 | Priority: 10 67 | 68 | IncludeIsMainRegex: '(Test)?$' 69 | IndentCaseLabels: false 70 | IndentWidth: 4 71 | IndentWrappedFunctionNames: false 72 | JavaScriptQuotes: Leave 73 | JavaScriptWrapImports: true 74 | KeepEmptyLinesAtTheStartOfBlocks: true 75 | MacroBlockBegin: '' 76 | MacroBlockEnd: '' 77 | MaxEmptyLinesToKeep: 2 78 | NamespaceIndentation: None 79 | ObjCBlockIndentWidth: 2 80 | ObjCSpaceAfterProperty: false 81 | ObjCSpaceBeforeProtocolList: true 82 | PenaltyBreakBeforeFirstCallParameter: 19 83 | PenaltyBreakComment: 300 84 | PenaltyBreakFirstLessLess: 120 85 | PenaltyBreakString: 1000 86 | PenaltyExcessCharacter: 1000000 87 | PenaltyReturnTypeOnItsOwnLine: 60 88 | PointerAlignment: Left 89 | ReflowComments: true 90 | SortIncludes: true 91 | SpaceAfterCStyleCast: false 92 | SpaceAfterTemplateKeyword: true 93 | SpaceBeforeAssignmentOperators: true 94 | SpaceBeforeParens: ControlStatements 95 | SpaceInEmptyParentheses: false 96 | SpacesBeforeTrailingComments: 1 97 | SpacesInAngles: false 98 | SpacesInContainerLiterals: true 99 | SpacesInCStyleCastParentheses: false 100 | SpacesInParentheses: false 101 | SpacesInSquareBrackets: false 102 | Standard: Cpp11 103 | TabWidth: 8 104 | UseTab: Never 105 | -------------------------------------------------------------------------------- /.conda/README.md: -------------------------------------------------------------------------------- 1 | # gr-howto conda recipe 2 | 3 | This recipe is for creating a package that can be installed into a [conda](https://docs.conda.io/en/latest/) environment. See the [Conda GNU Radio Guide](https://wiki.gnuradio.org/index.php/CondaInstall) for more information on using GNU Radio with conda. 4 | 5 | Packages for GNU Radio and some out-of-tree (OOT) modules are available through the [`conda-forge` channel](https://conda-forge.org/). If this OOT module is already available (search "gnuradio" on [anaconda.org](https://anaconda.org)), it is preferable to use that existing package rather than this recipe. 6 | 7 | #### Users 8 | 9 | - [Building the package](#building-the-package) 10 | 11 | #### Developers 12 | 13 | - [Modifying the recipe](#modifying-the-recipe) 14 | - [Continuous integration](#continuous-integration) 15 | 16 | 17 | ## Building the package 18 | 19 | (See the [Conda GNU Radio Guide](https://wiki.gnuradio.org/index.php/CondaInstall) if you are unfamiliar with how to use conda.) 20 | 21 | 1. Make sure that have `conda-build` and `conda-forge-pinning` installed and updated in your base environment: 22 | 23 | conda activate base 24 | conda install -n base conda-build conda-forge-pinning 25 | conda upgrade -n base conda-build conda-forge-pinning 26 | 27 | **Windows users only**: you will also need to have Microsoft's Visual C++ build tools installed. Usually you can do this by installing the [Community edition of Visual Studio](https://visualstudio.microsoft.com/free-developer-offers/) and then selecting a MSVC C++ x64/x86 build tools component under the list of "Individual Components". As of this writing, you will specifically need MSVC v141, i.e. the "MSVC v141 - VS2017 C++ x64/x86 build tools (v14.16)" component. If the build fails to find the version of MSVC it is looking for, try installing other (newer) versions. 28 | 29 | 2. Download the source code for this OOT module (which includes this recipe). Typically, this is done by using `git` and cloning the module's repository: 30 | 31 | git clone 32 | cd 33 | 34 | 3. Run `conda-build` on the recipe to create the package: 35 | 36 | (Linux and macOS) 37 | 38 | conda build .conda/recipe/ -m ${CONDA_PREFIX}/conda_build_config.yaml 39 | 40 | (Windows) 41 | 42 | conda build .conda\recipe\ -m %CONDA_PREFIX%\conda_build_config.yaml 43 | 44 | If you plan on using this package within an existing environment which uses a specific version of Python, specify the version of Python using the `--python` flag. You must use a version string that matches one of the strings listed under `python` in the `${CONDA_PREFIX}/conda_build_config.yaml` file, e.g: 45 | 46 | (Linux and macOS) 47 | 48 | conda build .conda/recipe/ -m ${CONDA_PREFIX}/conda_build_config.yaml --python="3.9.* *_cpython" 49 | 50 | (Windows) 51 | 52 | conda build .conda\recipe\ -m %CONDA_PREFIX%\conda_build_config.yaml --python="3.9.* *_cpython" 53 | 54 | If you encounter errors, consult with the OOT module maintainer or the maintainers of the [gnuradio feedstock](https://github.com/conda-forge/gnuradio-feedstock). It is possible that the recipe will need to be updated. 55 | 56 | 4. Install the package into an existing environment 57 | 58 | conda install --use-local -n gnuradio-EXAMPLE 59 | 60 | or create a new environment that includes the package: 61 | 62 | conda create -n test_env gnuradio-EXAMPLE 63 | 64 | 65 | ## Modifying the recipe 66 | 67 | This recipe is derived from a template, and so it is best to check it and make any necessary modifications. Likely changes include: 68 | 69 | - Populating metadata near the bottom of the `recipe/meta.yaml` file 70 | - Adding "host" (build-time) and "run" (run-time) dependencies specific to your module in `recipe/meta.yaml` 71 | - Adding special configuration flags or steps are necessary to carry out the build to the build scripts (`recipe/build.sh` for Linux/macOS and `recipe/bld.bat` for Windows) 72 | 73 | Specifying the versions of GNU Radio that your OOT is compatible with is one of the most important modifications. Following the instructions below, the module will be built against the conda-forge "pinned" version of GNU Radio, which is usually the latest version. 74 | 75 | - To override the pinned version of GNU Radio (e.g. for a branch that builds against an older version), specify the `gnuradio_core` key as instructed in `recipe/conda_build_config.yaml`. 76 | - If the module is compatible with multiple major versions of GNU Radio, and you want to build against multiple of them, you can also add extra versions to `recipe/conda_build_config.yaml` to expand the default build matrix. 77 | 78 | See the [conda-build documentation](https://docs.conda.io/projects/conda-build/en/latest/index.html) for details on how to write a conda recipe. 79 | 80 | 81 | ## Continuous integration 82 | 83 | Only a few steps are needed to use this recipe to build and test this OOT module using CI services. It can also be used to upload packages to [anaconda.org](https://anaconda.org) for others to download and use. 84 | 85 | 1. Make sure that have `conda-smithy` installed in your base conda environment: 86 | 87 | conda activate base 88 | conda install -n base conda-smithy 89 | conda upgrade -n base conda-smithy 90 | 91 | 2. Make any changes to the recipe and `conda-forge.yml` that are necessary. For example, if you plan on uploading packages to your own [anaconda.org](https://anaconda.org) channel, specify the channel name and label as the `channel_targets` key in `recipe/conda_build_config.yaml`. Commit the changes to your repository: 92 | 93 | git commit -a 94 | 95 | 3. "Re-render" the CI scripts by running conda-smithy from the root of your repository: 96 | 97 | conda-smithy rerender --feedstock_config .conda/conda-forge.yml -c auto 98 | 99 | This will create a commit that adds or updates the CI scripts that have been configured with `conda-forge.yml`. If you want to minimize extraneous files, you can remove some of the newly-created files that are not necessary outside of a typical conda-forge feedstock: 100 | 101 | git rm -f .github/workflows/automerge.yml .github/workflows/webservices.yml .circleci/config.yml 102 | git commit --amend -s 103 | 104 | When the CI is executed (on a pull request or commit), it will run one job per configuration file in `.ci_support` to build packages for various platforms, Python versions, and optionally `gnuradio` versions (by adding to `gnuradio_extra_pin` in `recipe/conda_build_config.yaml`). 105 | 106 | **You should repeat this step whenever the recipe is updated or when changes to the conda-forge infrastructure require all CI scripts to be updated.** 107 | 108 | Since the newly created files will be rewritten whenever conda-smithy is run, you should not edit any of the automatically-generated files in e.g. `.ci_support`, `.scripts`, or `.github/workflows/conda-build.yml`. 109 | 110 | 4. (optional) If you want to enable uploads of the packages to [anaconda.org](https://anaconda.org) whenever the CI is run from a commit on the branch specified in `conda-forge.yml`, you need to set an Anaconda Cloud API token to the `BINSTAR_TOKEN` environment variable. To generate a token, follow the instructions [here](https://docs.anaconda.com/anacondaorg/user-guide/tasks/work-with-accounts/#creating-access-tokens). To populate the `BINSTAR_TOKEN` environment variable for CI jobs, add the token as a secret by following, for example, the [Github docs](https://docs.github.com/en/actions/reference/encrypted-secrets). 111 | -------------------------------------------------------------------------------- /.conda/conda-forge.yml: -------------------------------------------------------------------------------- 1 | # See https://conda-forge.org/docs/maintainer/conda_forge_yml.html for 2 | # documentation on possible keys and values. 3 | 4 | # uncomment to enable cross-compiled osx-arm64 builds 5 | build_platform: 6 | osx_arm64: osx_64 7 | clone_depth: 0 8 | github_actions: 9 | store_build_artifacts: true 10 | os_version: 11 | linux_64: cos7 12 | provider: 13 | linux: github_actions 14 | osx: github_actions 15 | win: github_actions 16 | # uncomment to enable additional linux platforms 17 | linux_aarch64: github_actions 18 | linux_ppc64le: github_actions 19 | recipe_dir: .conda/recipe 20 | # skip unnecessary files since this is not a full-fledged conda-forge feedstock 21 | skip_render: 22 | - README.md 23 | - LICENSE.txt 24 | - .gitattributes 25 | - .gitignore 26 | - build-locally.py 27 | - LICENSE 28 | test: native_and_emulated 29 | # enable uploads to Anaconda Cloud from specified branches only 30 | upload_on_branch: conda 31 | -------------------------------------------------------------------------------- /.conda/recipe/bld.bat: -------------------------------------------------------------------------------- 1 | setlocal EnableDelayedExpansion 2 | @echo on 3 | 4 | :: Make a build folder and change to it 5 | cmake -E make_directory buildconda 6 | cd buildconda 7 | 8 | :: configure 9 | cmake -G "Ninja" ^ 10 | -DCMAKE_BUILD_TYPE:STRING=Release ^ 11 | -DCMAKE_INSTALL_PREFIX:PATH="%LIBRARY_PREFIX%" ^ 12 | -DCMAKE_PREFIX_PATH:PATH="%LIBRARY_PREFIX%" ^ 13 | -DGR_PYTHON_DIR:PATH="%SP_DIR%" ^ 14 | -DENABLE_DOXYGEN=OFF ^ 15 | -DENABLE_TESTING=ON ^ 16 | .. 17 | if errorlevel 1 exit 1 18 | 19 | :: build 20 | cmake --build . --config Release -- -j%CPU_COUNT% 21 | if errorlevel 1 exit 1 22 | 23 | :: install 24 | cmake --build . --config Release --target install 25 | if errorlevel 1 exit 1 26 | 27 | :: test 28 | ctest --build-config Release --output-on-failure --timeout 120 -j%CPU_COUNT% 29 | if errorlevel 1 exit 1 30 | -------------------------------------------------------------------------------- /.conda/recipe/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | 5 | cmake -E make_directory buildconda 6 | cd buildconda 7 | 8 | cmake_config_args=( 9 | -DCMAKE_BUILD_TYPE=Release 10 | -DCMAKE_INSTALL_PREFIX=$PREFIX 11 | -DLIB_SUFFIX="" 12 | -DENABLE_DOXYGEN=OFF 13 | -DENABLE_TESTING=ON 14 | ) 15 | 16 | cmake ${CMAKE_ARGS} -G "Ninja" .. "${cmake_config_args[@]}" 17 | cmake --build . --config Release -- -j${CPU_COUNT} 18 | cmake --build . --config Release --target install 19 | 20 | if [[ "${CONDA_BUILD_CROSS_COMPILATION:-}" != "1" || "${CROSSCOMPILING_EMULATOR}" != "" ]]; then 21 | ctest --build-config Release --output-on-failure --timeout 120 -j${CPU_COUNT} 22 | fi 23 | -------------------------------------------------------------------------------- /.conda/recipe/conda_build_config.yaml: -------------------------------------------------------------------------------- 1 | # this is the channel and label where packages will be uploaded to if enabled 2 | # (see ../README.md) 3 | channel_targets: 4 | - gnuradio main 5 | # override the conda-forge pin for gnuradio-core by uncommenting 6 | # and specifying a different version here 7 | #gnuradio_core: 8 | #- "3.10.1" 9 | gnuradio_extra_pin: 10 | # always leave one entry with the empty string 11 | - "" 12 | # add version strings here like to get builds for versions other than 13 | # the conda-forge-wide default or version specified above for gnuradio_core 14 | #- "3.9.5" 15 | -------------------------------------------------------------------------------- /.conda/recipe/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set oot_name = "inspector" %} 2 | {% set name = "gnuradio-" + oot_name %} 3 | {% set version = (environ.get("GIT_DESCRIBE_TAG_PEP440", "0.0.0." + datetime.datetime.now().strftime("%Y%m%d") + ".dev+" + environ.get("GIT_DESCRIBE_HASH", "local"))|string) %} 4 | 5 | package: 6 | name: {{ name|lower }} 7 | version: {{ version }} 8 | 9 | source: 10 | # use local path or git repository depending on if the build is local or done on CI 11 | path: "../.." # [not os.environ.get("CI")] 12 | git_url: {{ environ.get('FEEDSTOCK_ROOT', "../..") }} # [os.environ.get("CI")] 13 | 14 | build: 15 | number: 0 16 | skip: true # [ppc64le] 17 | 18 | requirements: 19 | build: 20 | - {{ compiler("c") }} 21 | - {{ compiler("cxx") }} 22 | - cmake 23 | - git 24 | - ninja 25 | - pkg-config 26 | # cross-compilation requirements 27 | - python # [build_platform != target_platform] 28 | - cross-python_{{ target_platform }} # [build_platform != target_platform] 29 | - numpy # [build_platform != target_platform] 30 | - pybind11 # [build_platform != target_platform] 31 | # Add extra build tool dependencies here 32 | # below are needed to link with Qt 33 | - {{ cdt('libice') }} # [linux] 34 | - {{ cdt('libselinux') }} # [linux] 35 | - {{ cdt('libsm') }} # [linux] 36 | - {{ cdt('libx11') }} # [linux] 37 | - {{ cdt('libxau') }} # [linux] 38 | - {{ cdt('libxcb') }} # [linux] 39 | - {{ cdt('libxdamage') }} # [linux] 40 | - {{ cdt('libxext') }} # [linux] 41 | - {{ cdt('libxfixes') }} # [linux] 42 | - {{ cdt('libxrender') }} # [linux] 43 | - {{ cdt('libxxf86vm') }} # [linux] 44 | - {{ cdt('libuuid') }} # [linux] 45 | - {{ cdt('mesa-dri-drivers') }} # [linux] 46 | - {{ cdt('mesa-libgl-devel') }} # [linux] 47 | 48 | host: 49 | - gmp # [linux] 50 | # the following two entries are for generating builds against specific GR versions 51 | - gnuradio-core # [not gnuradio_extra_pin] 52 | - gnuradio-core {{ gnuradio_extra_pin }}.* # [gnuradio_extra_pin] 53 | - gnuradio-qtgui 54 | - pip # [win] 55 | - pybind11 56 | - python 57 | - numpy 58 | - spdlog 59 | - volk 60 | # Add/remove library dependencies here 61 | - pyqt 62 | - qt-main 63 | - qwt 64 | 65 | run: 66 | - numpy 67 | - python 68 | # Add/remove runtime dependencies here 69 | - gnuradio-qtgui 70 | - pyqt 71 | - {{ pin_compatible('qwt', max_pin='x.x') }} 72 | 73 | test: 74 | commands: 75 | # verify that (some) headers get installed 76 | - test -f $PREFIX/include/gnuradio/{{ oot_name }}/api.h # [not win] 77 | - if not exist %PREFIX%\\Library\\include\\gnuradio\\{{ oot_name }}\\api.h exit 1 # [win] 78 | 79 | # verify that libraries get installed 80 | - test -f $PREFIX/lib/lib{{ name }}${SHLIB_EXT} # [not win] 81 | - if not exist %PREFIX%\\Library\\bin\\{{ name }}.dll exit 1 # [win] 82 | - if not exist %PREFIX%\\Library\\lib\\{{ name }}.lib exit 1 # [win] 83 | 84 | # verify that (some) GRC blocks get installed 85 | {% set blocks = ["inspector_ofdm_synchronizer_cc", "inspector_ofdm_zkf_c", "inspector_qtgui_inspector_sink_vf", "inspector_signal_detector_cvf", "inspector_signal_extractor_c", "inspector_signal_separator_c"] %} 86 | {% for block in blocks %} 87 | - test -f $PREFIX/share/gnuradio/grc/blocks/{{ block }}.block.yml # [not win] 88 | - if not exist %PREFIX%\\Library\\share\\gnuradio\\grc\\blocks\\{{ block }}.block.yml exit 1 # [win] 89 | {% endfor %} 90 | 91 | imports: 92 | # verify that the python module imports 93 | - gnuradio.{{ oot_name }} 94 | 95 | about: 96 | # For licenses, use the SPDX identifier, e.g: "GPL-2.0-only" instead of 97 | # "GNU General Public License version 2.0". See https://spdx.org/licenses/. 98 | # Include the license text by using the license_file entry set to the path 99 | # of the license text file within the source directory, e.g. "LICENSE". 100 | # See https://docs.conda.io/projects/conda-build/en/latest/resources/define-metadata.html#license-file 101 | 102 | home: https://github.com/gnuradio/gr-inspector 103 | license: GPL-3.0-or-later 104 | license_file: LICENSE 105 | summary: GNU Radio signal analysis toolbox 106 | description: > 107 | This GNU Radio module is developed to realize signal analysis abilities 108 | in typical block-structure. The module is capable of the following: 109 | 110 | Energy detection of continuous signals 111 | Filtering of detected signals 112 | OFDM parameter estimation (carrier spacing, symbol time) 113 | Blind OFDM synchronization 114 | Resampling of signals to constant rate 115 | -------------------------------------------------------------------------------- /.conda/recipe/yum_requirements.txt: -------------------------------------------------------------------------------- 1 | mesa-libGL 2 | mesa-dri-drivers 3 | libice 4 | libselinux 5 | libsm 6 | libX11 7 | libXcomposite 8 | libXcursor 9 | libXdamage 10 | libXext 11 | libXfixes 12 | libXi 13 | libXinerama 14 | libXrandr 15 | libXxf86vm 16 | xcb-util 17 | xcb-util-image 18 | xcb-util-keysyms 19 | xcb-util-renderutil 20 | xcb-util-wm 21 | xorg-x11-server-Xvfb 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # In GNU Radio 3.9+, pybind11 compares hash values of headers and source 2 | # files against knowns values. Conversion of values to CRLF on checkout 3 | # break those checks so keep LF values when files are subject to said checks 4 | # 5 | *.h text eol=lf 6 | *.c text eol=lf 7 | *.cc text eol=lf 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /examples/*.py 3 | /build 4 | /python/.unittests 5 | *.pyc 6 | .tags 7 | tags 8 | .ycm_extra_conf.py 9 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011-2020 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | # Select the release build type by default to get optimization flags. 10 | # This has to come before project() which otherwise initializes it. 11 | # Build type can still be overridden by setting -DCMAKE_BUILD_TYPE= 12 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") 13 | 14 | ######################################################################## 15 | # Project setup 16 | ######################################################################## 17 | cmake_minimum_required(VERSION 3.8) 18 | project(gr-inspector CXX C) 19 | enable_testing() 20 | 21 | # Install to PyBOMBS target prefix if defined 22 | if(DEFINED ENV{PYBOMBS_PREFIX}) 23 | set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX}) 24 | message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}") 25 | endif() 26 | 27 | # Select the release build type by default to get optimization flags 28 | if(NOT CMAKE_BUILD_TYPE) 29 | set(CMAKE_BUILD_TYPE "Release") 30 | message(STATUS "Build type not specified: defaulting to release.") 31 | endif(NOT CMAKE_BUILD_TYPE) 32 | set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") 33 | 34 | # Make sure our local CMake Modules path comes first 35 | list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) 36 | # Find gnuradio to get access to the cmake modules 37 | find_package(Gnuradio "3.10" REQUIRED COMPONENTS fft filter blocks) 38 | 39 | # Set the version information here 40 | set(VERSION_MAJOR 2) 41 | set(VERSION_API 0) 42 | set(VERSION_ABI 0) 43 | set(VERSION_PATCH git) 44 | 45 | cmake_policy(SET CMP0011 NEW) 46 | 47 | # Enable generation of compile_commands.json for code completion engines 48 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 49 | 50 | ######################################################################## 51 | # Minimum Version Requirements 52 | ######################################################################## 53 | 54 | include(GrMinReq) 55 | 56 | ######################################################################## 57 | # Compiler settings 58 | ######################################################################## 59 | 60 | include(GrCompilerSettings) 61 | 62 | ######################################################################## 63 | # Install directories 64 | ######################################################################## 65 | include(GrVersion) 66 | 67 | include(GrPlatform) #define LIB_SUFFIX 68 | 69 | find_package(Qt5 COMPONENTS Core Widgets REQUIRED) 70 | 71 | include(GrPython) 72 | GR_PYTHON_CHECK_MODULE("PyQt5" PyQt5 True PYQT5_FOUND) 73 | find_package(Qwt REQUIRED) 74 | 75 | if(NOT CMAKE_MODULES_DIR) 76 | set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake) 77 | endif(NOT CMAKE_MODULES_DIR) 78 | 79 | set(GR_INCLUDE_DIR include/gnuradio/inspector) 80 | set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/gnuradio-inspector) 81 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) 82 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) 83 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) 84 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) 85 | 86 | ######################################################################## 87 | # On Apple only, set install name and use rpath correctly, if not already set 88 | ######################################################################## 89 | if(APPLE) 90 | if(NOT CMAKE_INSTALL_NAME_DIR) 91 | set(CMAKE_INSTALL_NAME_DIR 92 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 93 | PATH "Library Install Name Destination Directory" FORCE) 94 | endif(NOT CMAKE_INSTALL_NAME_DIR) 95 | if(NOT CMAKE_INSTALL_RPATH) 96 | set(CMAKE_INSTALL_RPATH 97 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 98 | PATH "Library Install RPath" FORCE) 99 | endif(NOT CMAKE_INSTALL_RPATH) 100 | if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 101 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE 102 | BOOL "Do Build Using Library Install RPath" FORCE) 103 | endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 104 | endif(APPLE) 105 | 106 | ######################################################################## 107 | # Find gnuradio build dependencies 108 | ######################################################################## 109 | find_package(Doxygen) 110 | 111 | ######################################################################## 112 | # Setup doxygen option 113 | ######################################################################## 114 | if(DOXYGEN_FOUND) 115 | option(ENABLE_DOXYGEN "Build docs using Doxygen" ON) 116 | else(DOXYGEN_FOUND) 117 | option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) 118 | endif(DOXYGEN_FOUND) 119 | 120 | ######################################################################## 121 | # Create uninstall target 122 | ######################################################################## 123 | configure_file( 124 | ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 125 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 126 | @ONLY) 127 | 128 | add_custom_target(uninstall 129 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 130 | ) 131 | 132 | ######################################################################## 133 | # Add subdirectories 134 | ######################################################################## 135 | add_subdirectory(include/gnuradio/inspector) 136 | add_subdirectory(lib) 137 | add_subdirectory(apps) 138 | add_subdirectory(examples) 139 | add_subdirectory(docs) 140 | # NOTE: manually update below to use GRC to generate C++ flowgraphs w/o python 141 | if(ENABLE_PYTHON) 142 | message(STATUS "PYTHON and GRC components are enabled") 143 | add_subdirectory(python/inspector) 144 | add_subdirectory(grc) 145 | else(ENABLE_PYTHON) 146 | message(STATUS "PYTHON and GRC components are disabled") 147 | endif(ENABLE_PYTHON) 148 | 149 | ######################################################################## 150 | # Install cmake search helper for this library 151 | ######################################################################## 152 | 153 | install(FILES cmake/Modules/gnuradio-inspectorConfig.cmake 154 | DESTINATION ${GR_CMAKE_DIR} 155 | ) 156 | 157 | include(CMakePackageConfigHelpers) 158 | configure_package_config_file( 159 | ${PROJECT_SOURCE_DIR}/cmake/Modules/targetConfig.cmake.in 160 | ${CMAKE_CURRENT_BINARY_DIR}/cmake/Modules/${target}Config.cmake 161 | INSTALL_DESTINATION ${GR_CMAKE_DIR} 162 | ) 163 | 164 | install(FILES MANIFEST.yml 165 | RENAME MANIFEST-${VERSION_MAJOR}.${VERSION_API}.${VERSION_ABI}${VERSION_PATCH}.yml 166 | DESTINATION share/gnuradio/manifests/inspector) 167 | -------------------------------------------------------------------------------- /MANIFEST.md: -------------------------------------------------------------------------------- 1 | title: gr-inspector 2 | brief: A signal analysis toolbox for GNU Radio 3 | tags: 4 | - SDR 5 | - Signal Analysis 6 | - Spectrum Analysis 7 | - Signal Intelligence 8 | - OFDM 9 | author: 10 | - Sebastian Müller 11 | copyright_owner: 12 | - Sebastian Müller 13 | dependencies: 14 | - gnuradio, Qt5, Qwt 6.1.0 15 | gr_supported_version: 16 | - v3.7 17 | - v3.8 18 | license: GPLv3 19 | repo: https://github.com/gnuradio/gr-inspector 20 | website: https://grinspector.wordpress.com/ 21 | icon: https://raw.githubusercontent.com/gnuradio/gr-inspector/master/docs/doxygen/images/logo_body_big.png 22 | --- 23 | *Signal Analysis Toolbox for GNU Radio* 24 | 25 | This toolbox provides algorithms, blocks and tools for signal analysis and 26 | spectrum monitoring. Detailed functionality includes signal detection and 27 | signal filtering/mixing/decimating/resampling. Further, it is possible 28 | to estimate OFDM signal parameters and synchronize to a given OFDM signal. 29 | 30 | This project was initiated as a Google Summer of Code project and developed in 31 | cooperation with the *Communication Engineering Lab (CEL)* at the *Karlsruhe 32 | Institute of Technology (KIT)*, Germany, . 33 | -------------------------------------------------------------------------------- /MANIFEST.yml: -------------------------------------------------------------------------------- 1 | title: The INSPECTOR OOT Module 2 | version: 1.0 3 | brief: A signal analysis toolbox for GNU Radio 4 | tags: # Tags are arbitrary, but look at CGRAN what other authors are using 5 | - SDR 6 | - Signal Analysis 7 | - Spectrum Analysis 8 | - Signal Intelligence 9 | - OFDM 10 | author: 11 | - Sebastian Müller 12 | copyright_owner: 13 | - Sebastian Müller 14 | license: GPL-3.0-or-later 15 | gr_supported_version: 16 | - 3.7 17 | - 3.8 18 | - 3.9 19 | - 3.10 20 | repo: https://github.com/gnuradio/gr-inspector 21 | website: https://grinspector.wordpress.com/ 22 | icon: https://raw.githubusercontent.com/gnuradio/gr-inspector/master/docs/doxygen/images/logo_body_big.png 23 | description: |- 24 | This toolbox provides algorithms, blocks and tools for signal analysis and 25 | spectrum monitoring. Detailed functionality includes signal detection and 26 | signal filtering/mixing/decimating/resampling. Further, it is possible 27 | to estimate OFDM signal parameters and synchronize to a given OFDM signal. 28 | 29 | This project was initiated as a Google Summer of Code project and developed in 30 | cooperation with the *Communication Engineering Lab (CEL)* at the *Karlsruhe 31 | Institute of Technology (KIT)*, Germany, . 32 | file_format: 1 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 | 7 | # The Inspector (gr-inspector) 8 | 9 | ## Introduction 10 | This GNU Radio module is developed to realize signal analysis abilities in typical block-structure. The module is capable of the following: 11 | - Energy detection of continuous signals 12 | - Filtering of detected signals 13 | - OFDM parameter estimation (carrier spacing, symbol time) 14 | - Blind OFDM synchronization 15 | - Resampling of signals to constant rate 16 | - 3D Visualisation of FAM data, from gr-specest (not on GR 3.8 yet) 17 | - Using TensorFlow models for AMC (not on GR 3.8 yet) 18 | 19 | ## Installation 20 | 21 | To install the Inspector, the following dependencies are required: 22 | 23 | - [GNU Radio](https://github.com/gnuradio/gnuradio) 3.8 24 | - gr-blocks, gr-filter, gr-fft 25 | - Optional for tests: gr-analog, gr-channel 26 | - Qt5 27 | - Qwt 6.1.0 28 | 29 | This OOT follows the GNU Radio [development 30 | model](https://wiki.gnuradio.org/index.php/GNU_Radio_3.8_OOT_Module_Porting_Guide#Development_Model), 31 | there are different branches for compatibility with different GNU Radio 32 | versions. 33 | 34 | Install by the following shell commands: 35 | 36 | ``` 37 | git clone git@github.com:gnuradio/gr-inspector.git 38 | cd gr-inspector 39 | mkdir build 40 | cd build 41 | cmake .. 42 | make -j4 43 | sudo make install 44 | ``` 45 | 46 | ## Usage 47 | Get inspired by the examples. There are flowgraphs for each block that should explain how to use them. 48 | 49 | For detailed information about each block, visit the Doxygen HTML pages. 50 | ## Brief block description 51 | 52 | A typical inspector flowgraph could look like this: 53 | ![A typical inspector flowgraph](https://grinspector.files.wordpress.com/2016/05/decentral.png) 54 | 55 | #### Signal Detector 56 | Performs an energy detection of continuous input signals. A threshold in dB can be set or an autmatic threshold calculation can be used. 57 | 58 | #### Inspector GUI 59 | GUI where the spectrum is displayed along with signal markers for the detected signals. Also, signal can be selected manually in this block. 60 | 61 | #### Signal Separator 62 | Takes the signal info from the previous blocks and performs a down-mixing, filtering and decimation of each detected signal. The samples for each signal are passed on as a message. 63 | 64 | #### Signal Extractor 65 | Adapter block to extract the samples of one signal out of the messages from the Signal Separator. Output is again a complex stream. 66 | 67 | Resampling can be used to assure a constant output sample rate of the stream. (Needed for FM demod for instance.) 68 | 69 | #### OFDM Estimator 70 | Estimates the parameters subcarrier spacing, symbol time, FFT size and cyclic prefix length for a input signal. The signal should not be oversampled for this block. 71 | 72 | #### OFDM Synchronizer 73 | After OFDM parameter estimation, the signal is frequency synced and symbol beginnings are marked with stream tags. 74 | 75 | ## Google Summer of Code 76 | This GNU Radio module is part of the Google Summer of Code (GSoC) program 2016. The target is to develop a signal analysis / signal intelligence toolbox with the following capabilities: 77 | 78 | - Automatic signal detection 79 | - Automatic modulation classification 80 | - OFDM parameter estimation and synchronization 81 | - GUI feedback 82 | - Doxygen documentation 83 | 84 | Read the full proposal [here](https://github.com/sbmueller/gsoc-proposal/blob/master/sigint-proposal.pdf). 85 | 86 | This project was developed in cooperation with the [Communications Engineering Lab](http://www.cel.kit.edu/) of the Karlsruhe Institute of Technology. 87 | 88 | The modulation classification is developed by @chrisruk during ESA Summer of Code in Space program. 89 | 90 | ## Pybind11 QT binding issues 91 | Trying to generate the qt_gui_inspector_sink_vf module python bindings, you may get an error that the "qapplication.h" include cannot be found. Use this 92 | command and modify the include directory according to your system: 93 | ``` 94 | gr_modtool bind qtgui_inspector_sink_vf --addl_includes /usr/include/x86_64-linux-gnu/qt5/,/usr/include/x86_64-linux-gnu/qt5/QtWidgets -D"__PIC__ 2" 95 | ``` 96 | Add to the qtgui_inspector_sink_vf_python.cc : 97 | ``` 98 | #include 99 | ``` 100 | ## License 101 | This software is Copyright © 2016 Free Software Foundation, Inc. and part of GNU Radio. It is free software, and is released under the [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) License. 102 | 103 | ## Contact/Help 104 | If you run into problems installing or using gr-inspector, the GNU Radio [mailing list](https://wiki.gnuradio.org/index.php/MailingLists) is the right place to get help. There are many people who will provide assistance. **Please do provide a complete problem description containing** 105 | 106 | 1. What exactly where you trying to do? 107 | 2. What steps did you perform to achieve this? 108 | 3. What happend (with complete verbose output)? 109 | 4. Why do you think something went wrong? What should have happend instead? 110 | 111 | Visit [How to report errors](https://wiki.gnuradio.org/index.php/ReportingErrors) for more detailed instructions. 112 | 113 | **Please only use GitHub issues for actual bugs and improvements!** "This command is not working on my machine" is not a bug. 114 | 115 | Maintainer of this module: 116 | 117 | Sebastian Müller
118 | gsenpo[at]gmail.com 119 | 120 | Christopher Richardson
121 | chrisrichardsonuk[at]gmail.com 122 | 123 | If you want to know more about the development process, please visit the [blog](https://grinspector.wordpress.com/). 124 | -------------------------------------------------------------------------------- /apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | include(GrPython) 10 | 11 | GR_PYTHON_INSTALL( 12 | PROGRAMS 13 | DESTINATION bin 14 | ) 15 | -------------------------------------------------------------------------------- /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 therefore. 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 | -------------------------------------------------------------------------------- /cmake/Modules/gnuradio-inspectorConfig.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | 3 | PKG_CHECK_MODULES(PC_GR_INSPECTOR gnuradio-inspector) 4 | 5 | FIND_PATH( 6 | GR_INSPECTOR_INCLUDE_DIRS 7 | NAMES gnuradio/inspector/api.h 8 | HINTS $ENV{INSPECTOR_DIR}/include 9 | ${PC_INSPECTOR_INCLUDEDIR} 10 | PATHS ${CMAKE_INSTALL_PREFIX}/include 11 | /usr/local/include 12 | /usr/include 13 | ) 14 | 15 | FIND_LIBRARY( 16 | GR_INSPECTOR_LIBRARIES 17 | NAMES gnuradio-inspector 18 | HINTS $ENV{INSPECTOR_DIR}/lib 19 | ${PC_INSPECTOR_LIBDIR} 20 | PATHS ${CMAKE_INSTALL_PREFIX}/lib 21 | ${CMAKE_INSTALL_PREFIX}/lib64 22 | /usr/local/lib 23 | /usr/local/lib64 24 | /usr/lib 25 | /usr/lib64 26 | ) 27 | 28 | include("${CMAKE_CURRENT_LIST_DIR}/gnuradio-inspectorTarget.cmake") 29 | 30 | INCLUDE(FindPackageHandleStandardArgs) 31 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GR_INSPECTOR DEFAULT_MSG GR_INSPECTOR_LIBRARIES GR_INSPECTOR_INCLUDE_DIRS) 32 | MARK_AS_ADVANCED(GR_INSPECTOR_LIBRARIES GR_INSPECTOR_INCLUDE_DIRS) 33 | -------------------------------------------------------------------------------- /cmake/Modules/targetConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | # 7 | 8 | include(CMakeFindDependencyMacro) 9 | 10 | set(target_deps "@TARGET_DEPENDENCIES@") 11 | foreach(dep IN LISTS target_deps) 12 | find_dependency(${dep}) 13 | endforeach() 14 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGET@Targets.cmake") 15 | -------------------------------------------------------------------------------- /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 was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Setup dependencies 11 | ######################################################################## 12 | find_package(Doxygen) 13 | 14 | ######################################################################## 15 | # Begin conditional configuration 16 | ######################################################################## 17 | if(ENABLE_DOXYGEN) 18 | 19 | ######################################################################## 20 | # Add subdirectories 21 | ######################################################################## 22 | add_subdirectory(doxygen) 23 | 24 | endif(ENABLE_DOXYGEN) 25 | -------------------------------------------------------------------------------- /docs/README.inspector: -------------------------------------------------------------------------------- 1 | This is the inspector-write-a-block package meant as a guide to building 2 | out-of-tree packages. To use the inspector blocks, the Python namespaces 3 | is in 'inspector', which is imported as: 4 | 5 | import gnuradio.inspector as inspector 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(inspector) 12 | -------------------------------------------------------------------------------- /docs/doxygen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Create the doxygen configuration file 11 | ######################################################################## 12 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} top_srcdir) 13 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} top_builddir) 14 | file(TO_NATIVE_PATH ${CMAKE_SOURCE_DIR} abs_top_srcdir) 15 | file(TO_NATIVE_PATH ${CMAKE_BINARY_DIR} abs_top_builddir) 16 | 17 | set(HAVE_DOT ${DOXYGEN_DOT_FOUND}) 18 | set(enable_html_docs YES) 19 | set(enable_latex_docs NO) 20 | set(enable_mathjax NO) 21 | set(enable_xml_docs YES) 22 | 23 | configure_file( 24 | ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in 25 | ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 26 | @ONLY) 27 | 28 | set(BUILT_DIRS ${CMAKE_CURRENT_BINARY_DIR}/xml ${CMAKE_CURRENT_BINARY_DIR}/html) 29 | 30 | ######################################################################## 31 | # Make and install doxygen docs 32 | ######################################################################## 33 | add_custom_command( 34 | OUTPUT ${BUILT_DIRS} 35 | COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 36 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 37 | COMMENT "Generating documentation with doxygen" 38 | ) 39 | 40 | add_custom_target(doxygen_target ALL DEPENDS ${BUILT_DIRS}) 41 | 42 | install(DIRECTORY ${BUILT_DIRS} DESTINATION ${GR_PKG_DOC_DIR}) 43 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-inspector 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Python interface to contents of doxygen xml documentation. 12 | 13 | Example use: 14 | See the contents of the example folder for the C++ and 15 | doxygen-generated xml used in this example. 16 | 17 | >>> # Parse the doxygen docs. 18 | >>> import os 19 | >>> this_dir = os.path.dirname(globals()['__file__']) 20 | >>> xml_path = this_dir + "/example/xml/" 21 | >>> di = DoxyIndex(xml_path) 22 | 23 | Get a list of all top-level objects. 24 | 25 | >>> print([mem.name() for mem in di.members()]) 26 | [u'Aadvark', u'aadvarky_enough', u'main'] 27 | 28 | Get all functions. 29 | 30 | >>> print([mem.name() for mem in di.in_category(DoxyFunction)]) 31 | [u'aadvarky_enough', u'main'] 32 | 33 | Check if an object is present. 34 | 35 | >>> di.has_member(u'Aadvark') 36 | True 37 | >>> di.has_member(u'Fish') 38 | False 39 | 40 | Get an item by name and check its properties. 41 | 42 | >>> aad = di.get_member(u'Aadvark') 43 | >>> print(aad.brief_description) 44 | Models the mammal Aadvark. 45 | >>> print(aad.detailed_description) 46 | Sadly the model is incomplete and cannot capture all aspects of an aadvark yet. 47 | 48 | This line is uninformative and is only to test line breaks in the comments. 49 | >>> [mem.name() for mem in aad.members()] 50 | [u'aadvarkness', u'print', u'Aadvark', u'get_aadvarkness'] 51 | >>> aad.get_member(u'print').brief_description 52 | u'Outputs the vital aadvark statistics.' 53 | 54 | """ 55 | 56 | from .doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther 57 | 58 | 59 | def _test(): 60 | import os 61 | this_dir = os.path.dirname(globals()['__file__']) 62 | xml_path = this_dir + "/example/xml/" 63 | di = DoxyIndex(xml_path) 64 | # Get the Aadvark class 65 | aad = di.get_member('Aadvark') 66 | aad.brief_description 67 | import doctest 68 | return doctest.testmod() 69 | 70 | 71 | if __name__ == "__main__": 72 | _test() 73 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/base.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-inspector 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | A base class is created. 12 | 13 | Classes based upon this are used to make more user-friendly interfaces 14 | to the doxygen xml docs than the generated classes provide. 15 | """ 16 | 17 | import os 18 | import pdb 19 | 20 | from xml.parsers.expat import ExpatError 21 | 22 | from .generated import compound 23 | 24 | 25 | class Base(object): 26 | 27 | class Duplicate(Exception): 28 | pass 29 | 30 | class NoSuchMember(Exception): 31 | pass 32 | 33 | class ParsingError(Exception): 34 | pass 35 | 36 | def __init__(self, parse_data, top=None): 37 | self._parsed = False 38 | self._error = False 39 | self._parse_data = parse_data 40 | self._members = [] 41 | self._dict_members = {} 42 | self._in_category = {} 43 | self._data = {} 44 | if top is not None: 45 | self._xml_path = top._xml_path 46 | # Set up holder of references 47 | else: 48 | top = self 49 | self._refs = {} 50 | self._xml_path = parse_data 51 | self.top = top 52 | 53 | @classmethod 54 | def from_refid(cls, refid, top=None): 55 | """ Instantiate class from a refid rather than parsing object. """ 56 | # First check to see if its already been instantiated. 57 | if top is not None and refid in top._refs: 58 | return top._refs[refid] 59 | # Otherwise create a new instance and set refid. 60 | inst = cls(None, top=top) 61 | inst.refid = refid 62 | inst.add_ref(inst) 63 | return inst 64 | 65 | @classmethod 66 | def from_parse_data(cls, parse_data, top=None): 67 | refid = getattr(parse_data, 'refid', None) 68 | if refid is not None and top is not None and refid in top._refs: 69 | return top._refs[refid] 70 | inst = cls(parse_data, top=top) 71 | if refid is not None: 72 | inst.refid = refid 73 | inst.add_ref(inst) 74 | return inst 75 | 76 | def add_ref(self, obj): 77 | if hasattr(obj, 'refid'): 78 | self.top._refs[obj.refid] = obj 79 | 80 | mem_classes = [] 81 | 82 | def get_cls(self, mem): 83 | for cls in self.mem_classes: 84 | if cls.can_parse(mem): 85 | return cls 86 | raise Exception(("Did not find a class for object '%s'." 87 | % (mem.get_name()))) 88 | 89 | def convert_mem(self, mem): 90 | try: 91 | cls = self.get_cls(mem) 92 | converted = cls.from_parse_data(mem, self.top) 93 | if converted is None: 94 | raise Exception('No class matched this object.') 95 | self.add_ref(converted) 96 | return converted 97 | except Exception as e: 98 | print(e) 99 | 100 | @classmethod 101 | def includes(cls, inst): 102 | return isinstance(inst, cls) 103 | 104 | @classmethod 105 | def can_parse(cls, obj): 106 | return False 107 | 108 | def _parse(self): 109 | self._parsed = True 110 | 111 | def _get_dict_members(self, cat=None): 112 | """ 113 | For given category a dictionary is returned mapping member names to 114 | members of that category. For names that are duplicated the name is 115 | mapped to None. 116 | """ 117 | self.confirm_no_error() 118 | if cat not in self._dict_members: 119 | new_dict = {} 120 | for mem in self.in_category(cat): 121 | if mem.name() not in new_dict: 122 | new_dict[mem.name()] = mem 123 | else: 124 | new_dict[mem.name()] = self.Duplicate 125 | self._dict_members[cat] = new_dict 126 | return self._dict_members[cat] 127 | 128 | def in_category(self, cat): 129 | self.confirm_no_error() 130 | if cat is None: 131 | return self._members 132 | if cat not in self._in_category: 133 | self._in_category[cat] = [mem for mem in self._members 134 | if cat.includes(mem)] 135 | return self._in_category[cat] 136 | 137 | def get_member(self, name, cat=None): 138 | self.confirm_no_error() 139 | # Check if it's in a namespace or class. 140 | bits = name.split('::') 141 | first = bits[0] 142 | rest = '::'.join(bits[1:]) 143 | member = self._get_dict_members(cat).get(first, self.NoSuchMember) 144 | # Raise any errors that are returned. 145 | if member in set([self.NoSuchMember, self.Duplicate]): 146 | raise member() 147 | if rest: 148 | return member.get_member(rest, cat=cat) 149 | return member 150 | 151 | def has_member(self, name, cat=None): 152 | try: 153 | mem = self.get_member(name, cat=cat) 154 | return True 155 | except self.NoSuchMember: 156 | return False 157 | 158 | def data(self): 159 | self.confirm_no_error() 160 | return self._data 161 | 162 | def members(self): 163 | self.confirm_no_error() 164 | return self._members 165 | 166 | def process_memberdefs(self): 167 | mdtss = [] 168 | for sec in self._retrieved_data.compounddef.sectiondef: 169 | mdtss += sec.memberdef 170 | # At the moment we lose all information associated with sections. 171 | # Sometimes a memberdef is in several sectiondef. 172 | # We make sure we don't get duplicates here. 173 | uniques = set([]) 174 | for mem in mdtss: 175 | converted = self.convert_mem(mem) 176 | pair = (mem.name, mem.__class__) 177 | if pair not in uniques: 178 | uniques.add(pair) 179 | self._members.append(converted) 180 | 181 | def retrieve_data(self): 182 | filename = os.path.join(self._xml_path, self.refid + '.xml') 183 | try: 184 | self._retrieved_data = compound.parse(filename) 185 | except ExpatError: 186 | print('Error in xml in file %s' % filename) 187 | self._error = True 188 | self._retrieved_data = None 189 | 190 | def check_parsed(self): 191 | if not self._parsed: 192 | self._parse() 193 | 194 | def confirm_no_error(self): 195 | self.check_parsed() 196 | if self._error: 197 | raise self.ParsingError() 198 | 199 | def error(self): 200 | self.check_parsed() 201 | return self._error 202 | 203 | def name(self): 204 | # first see if we can do it without processing. 205 | if self._parse_data is not None: 206 | return self._parse_data.name 207 | self.check_parsed() 208 | return self._retrieved_data.compounddef.name 209 | -------------------------------------------------------------------------------- /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/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 | from . import compound 12 | 13 | from . import indexsuper as supermod 14 | 15 | 16 | class DoxygenTypeSub(supermod.DoxygenType): 17 | def __init__(self, version=None, compound=None): 18 | supermod.DoxygenType.__init__(self, version, compound) 19 | 20 | def find_compounds_and_members(self, details): 21 | """ 22 | Returns a list of all compounds and their members which match details 23 | """ 24 | 25 | results = [] 26 | for compound in self.compound: 27 | members = compound.find_members(details) 28 | if members: 29 | results.append([compound, members]) 30 | else: 31 | if details.match(compound): 32 | results.append([compound, []]) 33 | 34 | return results 35 | 36 | 37 | supermod.DoxygenType.subclass = DoxygenTypeSub 38 | # end class DoxygenTypeSub 39 | 40 | 41 | class CompoundTypeSub(supermod.CompoundType): 42 | def __init__(self, kind=None, refid=None, name='', member=None): 43 | supermod.CompoundType.__init__(self, kind, refid, name, member) 44 | 45 | def find_members(self, details): 46 | """ 47 | Returns a list of all members which match details 48 | """ 49 | 50 | results = [] 51 | 52 | for member in self.member: 53 | if details.match(member): 54 | results.append(member) 55 | 56 | return results 57 | 58 | 59 | supermod.CompoundType.subclass = CompoundTypeSub 60 | # end class CompoundTypeSub 61 | 62 | 63 | class MemberTypeSub(supermod.MemberType): 64 | 65 | def __init__(self, kind=None, refid=None, name=''): 66 | supermod.MemberType.__init__(self, kind, refid, name) 67 | 68 | 69 | supermod.MemberType.subclass = MemberTypeSub 70 | # end class MemberTypeSub 71 | 72 | 73 | def parse(inFilename): 74 | 75 | doc = minidom.parse(inFilename) 76 | rootNode = doc.documentElement 77 | rootObj = supermod.DoxygenType.factory() 78 | rootObj.build(rootNode) 79 | 80 | return rootObj 81 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/text.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010 Free Software Foundation, Inc. 3 | # 4 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | # This file is a part of gr-inspector 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Utilities for extracting text from generated classes. 12 | """ 13 | 14 | 15 | def is_string(txt): 16 | if isinstance(txt, str): 17 | return True 18 | try: 19 | if isinstance(txt, str): 20 | return True 21 | except NameError: 22 | pass 23 | return False 24 | 25 | 26 | def description(obj): 27 | if obj is None: 28 | return None 29 | return description_bit(obj).strip() 30 | 31 | 32 | def description_bit(obj): 33 | if hasattr(obj, 'content'): 34 | contents = [description_bit(item) for item in obj.content] 35 | result = ''.join(contents) 36 | elif hasattr(obj, 'content_'): 37 | contents = [description_bit(item) for item in obj.content_] 38 | result = ''.join(contents) 39 | elif hasattr(obj, 'value'): 40 | result = description_bit(obj.value) 41 | elif is_string(obj): 42 | return obj 43 | else: 44 | raise Exception( 45 | 'Expecting a string or something with content, content_ or value attribute') 46 | # If this bit is a paragraph then add one some line breaks. 47 | if hasattr(obj, 'name') and obj.name == 'para': 48 | result += "\n\n" 49 | return result 50 | -------------------------------------------------------------------------------- /docs/doxygen/other/group_defs.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | * \defgroup block GNU Radio INSPECTOR C++ Signal Processing Blocks 3 | * \brief All C++ blocks that can be used from the INSPECTOR GNU Radio 4 | * module are listed here or in the subcategories below. 5 | * 6 | */ 7 | -------------------------------------------------------------------------------- /docs/doxygen/other/main_page.dox: -------------------------------------------------------------------------------- 1 | /*! \mainpage 2 | 3 | Welcome to the GNU Radio INSPECTOR Block 4 | 5 | This is the intro page for the Doxygen manual generated for the INSPECTOR 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/doxygen/pydoc_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef PYDOC_MACROS_H 2 | #define PYDOC_MACROS_H 3 | 4 | #define __EXPAND(x) x 5 | #define __COUNT(_1, _2, _3, _4, _5, _6, _7, COUNT, ...) COUNT 6 | #define __VA_SIZE(...) __EXPAND(__COUNT(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1)) 7 | #define __CAT1(a, b) a##b 8 | #define __CAT2(a, b) __CAT1(a, b) 9 | #define __DOC1(n1) __doc_##n1 10 | #define __DOC2(n1, n2) __doc_##n1##_##n2 11 | #define __DOC3(n1, n2, n3) __doc_##n1##_##n2##_##n3 12 | #define __DOC4(n1, n2, n3, n4) __doc_##n1##_##n2##_##n3##_##n4 13 | #define __DOC5(n1, n2, n3, n4, n5) __doc_##n1##_##n2##_##n3##_##n4##_##n5 14 | #define __DOC6(n1, n2, n3, n4, n5, n6) __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6 15 | #define __DOC7(n1, n2, n3, n4, n5, n6, n7) \ 16 | __doc_##n1##_##n2##_##n3##_##n4##_##n5##_##n6##_##n7 17 | #define DOC(...) __EXPAND(__EXPAND(__CAT2(__DOC, __VA_SIZE(__VA_ARGS__)))(__VA_ARGS__)) 18 | 19 | #endif // PYDOC_MACROS_H 20 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | install(FILES live_fm_demod.grc 2 | live_signal_detection.grc 3 | ofdm_estimation.grc 4 | ofdm_sync.grc 5 | recorder.grc 6 | signal_detection.grc 7 | signal_separation.grc 8 | DESTINATION share/gnuradio/examples/inspector) 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/live_fm_demod.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: live_fm_demod 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | window_size: '' 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: freq 37 | id: variable_qtgui_range 38 | parameters: 39 | comment: '' 40 | gui_hint: '' 41 | label: freq 42 | min_len: '200' 43 | orient: QtCore.Qt.Horizontal 44 | rangeType: float 45 | start: 90e6 46 | step: '10000' 47 | stop: 110e6 48 | value: 101.8e6 49 | widget: counter_slider 50 | states: 51 | bus_sink: false 52 | bus_source: false 53 | bus_structure: null 54 | coordinate: [312, 8.0] 55 | rotation: 0 56 | state: enabled 57 | - name: samp_rate 58 | id: variable 59 | parameters: 60 | comment: '' 61 | value: 1e6 62 | states: 63 | bus_sink: false 64 | bus_source: false 65 | bus_structure: null 66 | coordinate: [576, 12.0] 67 | rotation: 0 68 | state: enabled 69 | - name: analog_wfm_rcv_0 70 | id: analog_wfm_rcv 71 | parameters: 72 | affinity: '' 73 | alias: '' 74 | audio_decimation: '2' 75 | comment: '' 76 | deemph_tau: 75e-6 77 | maxoutbuf: '0' 78 | minoutbuf: '0' 79 | quad_rate: '96000' 80 | states: 81 | bus_sink: false 82 | bus_source: false 83 | bus_structure: null 84 | coordinate: [1448, 552.0] 85 | rotation: 0 86 | state: enabled 87 | - name: audio_sink_0 88 | id: audio_sink 89 | parameters: 90 | affinity: '' 91 | alias: '' 92 | comment: '' 93 | device_name: '' 94 | num_inputs: '1' 95 | ok_to_block: 'True' 96 | samp_rate: '48000' 97 | states: 98 | bus_sink: false 99 | bus_source: false 100 | bus_structure: null 101 | coordinate: [1768, 684.0] 102 | rotation: 0 103 | state: enabled 104 | - name: inspector_qtgui_sink_vf_0 105 | id: inspector_qtgui_sink_vf 106 | parameters: 107 | affinity: '' 108 | alias: '' 109 | cfreq: '0' 110 | comment: '' 111 | fft_len: '1024' 112 | gui_hint: '' 113 | manual: 'True' 114 | maxoutbuf: '0' 115 | minoutbuf: '0' 116 | msgports: '1' 117 | rf_unit: '1' 118 | samp_rate: samp_rate 119 | states: 120 | bus_sink: false 121 | bus_source: false 122 | bus_structure: null 123 | coordinate: [1088, 160.0] 124 | rotation: 0 125 | state: enabled 126 | - name: inspector_signal_detector_cvf_0 127 | id: inspector_signal_detector_cvf 128 | parameters: 129 | affinity: '' 130 | alias: '' 131 | auto: 'False' 132 | avg: '0.8' 133 | comment: '' 134 | fft_len: ' 1024' 135 | logfile: '' 136 | maxoutbuf: '0' 137 | min_bw: '5000' 138 | minoutbuf: '0' 139 | quant: '0.0001' 140 | samp_rate: samp_rate 141 | sensitivity: ' 0.2' 142 | threshold: '-50' 143 | window: window.WIN_BLACKMAN_hARRIS 144 | states: 145 | bus_sink: false 146 | bus_source: false 147 | bus_structure: null 148 | coordinate: [552, 160.0] 149 | rotation: 0 150 | state: enabled 151 | - name: inspector_signal_extractor_c_0 152 | id: inspector_signal_extractor_c 153 | parameters: 154 | affinity: '' 155 | alias: '' 156 | comment: '' 157 | maxoutbuf: '0' 158 | minoutbuf: '0' 159 | osf: '1' 160 | rate: '96000' 161 | resample: 'True' 162 | signal: '0' 163 | states: 164 | bus_sink: false 165 | bus_source: false 166 | bus_structure: null 167 | coordinate: [1096, 524.0] 168 | rotation: 0 169 | state: enabled 170 | - name: inspector_signal_separator_c_0 171 | id: inspector_signal_separator_c 172 | parameters: 173 | affinity: '' 174 | alias: '' 175 | comment: '' 176 | file: 'False' 177 | maxoutbuf: '0' 178 | minoutbuf: '0' 179 | oversample: '1.0' 180 | samp_rate: samp_rate 181 | taps_file: '' 182 | trans_width: '0.1' 183 | window: window.WIN_HAMMING 184 | states: 185 | bus_sink: false 186 | bus_source: false 187 | bus_structure: null 188 | coordinate: [608, 516.0] 189 | rotation: 0 190 | state: enabled 191 | - name: qtgui_time_sink_x_0 192 | id: qtgui_time_sink_x 193 | parameters: 194 | affinity: '' 195 | alias: '' 196 | alpha1: '1.0' 197 | alpha10: '1.0' 198 | alpha2: '1.0' 199 | alpha3: '1.0' 200 | alpha4: '1.0' 201 | alpha5: '1.0' 202 | alpha6: '1.0' 203 | alpha7: '1.0' 204 | alpha8: '1.0' 205 | alpha9: '1.0' 206 | autoscale: 'False' 207 | axislabels: 'True' 208 | color1: blue 209 | color10: dark blue 210 | color2: red 211 | color3: green 212 | color4: black 213 | color5: cyan 214 | color6: magenta 215 | color7: yellow 216 | color8: dark red 217 | color9: dark green 218 | comment: '' 219 | ctrlpanel: 'False' 220 | entags: 'True' 221 | grid: 'False' 222 | gui_hint: '' 223 | label1: '' 224 | label10: '' 225 | label2: '' 226 | label3: '' 227 | label4: '' 228 | label5: '' 229 | label6: '' 230 | label7: '' 231 | label8: '' 232 | label9: '' 233 | legend: 'True' 234 | marker1: '-1' 235 | marker10: '-1' 236 | marker2: '-1' 237 | marker3: '-1' 238 | marker4: '-1' 239 | marker5: '-1' 240 | marker6: '-1' 241 | marker7: '-1' 242 | marker8: '-1' 243 | marker9: '-1' 244 | name: '""' 245 | nconnections: '1' 246 | size: '1024' 247 | srate: samp_rate 248 | stemplot: 'False' 249 | style1: '1' 250 | style10: '1' 251 | style2: '1' 252 | style3: '1' 253 | style4: '1' 254 | style5: '1' 255 | style6: '1' 256 | style7: '1' 257 | style8: '1' 258 | style9: '1' 259 | tr_chan: '0' 260 | tr_delay: '0' 261 | tr_level: '0.0' 262 | tr_mode: qtgui.TRIG_MODE_AUTO 263 | tr_slope: qtgui.TRIG_SLOPE_POS 264 | tr_tag: '""' 265 | type: float 266 | update_time: '0.01' 267 | width1: '1' 268 | width10: '1' 269 | width2: '1' 270 | width3: '1' 271 | width4: '1' 272 | width5: '1' 273 | width6: '1' 274 | width7: '1' 275 | width8: '1' 276 | width9: '1' 277 | ylabel: Amplitude 278 | ymax: '1' 279 | ymin: '-1' 280 | yunit: '""' 281 | states: 282 | bus_sink: false 283 | bus_source: false 284 | bus_structure: null 285 | coordinate: [1776, 416.0] 286 | rotation: 0 287 | state: enabled 288 | - name: soapy_rtlsdr_source_0 289 | id: soapy_rtlsdr_source 290 | parameters: 291 | affinity: '' 292 | agc: 'False' 293 | alias: '' 294 | center_freq: freq 295 | comment: '' 296 | dev_args: '' 297 | freq_correction: '0' 298 | gain: '20' 299 | maxoutbuf: '0' 300 | minoutbuf: '0' 301 | samp_rate: samp_rate 302 | type: fc32 303 | states: 304 | bus_sink: false 305 | bus_source: false 306 | bus_structure: null 307 | coordinate: [96, 244.0] 308 | rotation: 0 309 | state: true 310 | 311 | connections: 312 | - [analog_wfm_rcv_0, '0', audio_sink_0, '0'] 313 | - [analog_wfm_rcv_0, '0', qtgui_time_sink_x_0, '0'] 314 | - [inspector_qtgui_sink_vf_0, map_out, inspector_signal_separator_c_0, map_in] 315 | - [inspector_signal_detector_cvf_0, '0', inspector_qtgui_sink_vf_0, '0'] 316 | - [inspector_signal_detector_cvf_0, map_out, inspector_qtgui_sink_vf_0, map_in] 317 | - [inspector_signal_extractor_c_0, '0', analog_wfm_rcv_0, '0'] 318 | - [inspector_signal_separator_c_0, sig_out, inspector_signal_extractor_c_0, sig_in] 319 | - [soapy_rtlsdr_source_0, '0', inspector_signal_detector_cvf_0, '0'] 320 | - [soapy_rtlsdr_source_0, '0', inspector_signal_separator_c_0, '0'] 321 | 322 | metadata: 323 | file_format: 1 324 | grc_version: v3.11.0.0git-73-ga44ffb7b 325 | -------------------------------------------------------------------------------- /examples/live_signal_detection.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: Custom 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: live_signal_detection 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | window_size: '' 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: samp_rate 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: '500000' 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [536, 12.0] 46 | rotation: 0 47 | state: enabled 48 | - name: thres 49 | id: variable_qtgui_range 50 | parameters: 51 | comment: '' 52 | gui_hint: '' 53 | label: Threshold 54 | min_len: '200' 55 | orient: QtCore.Qt.Horizontal 56 | rangeType: float 57 | start: '-120' 58 | step: '1' 59 | stop: '50' 60 | value: '-65' 61 | widget: counter_slider 62 | states: 63 | bus_sink: false 64 | bus_source: false 65 | bus_structure: null 66 | coordinate: [304, 8.0] 67 | rotation: 0 68 | state: enabled 69 | - name: blocks_message_debug_0 70 | id: blocks_message_debug 71 | parameters: 72 | affinity: '' 73 | alias: '' 74 | comment: '' 75 | en_uvec: 'True' 76 | states: 77 | bus_sink: false 78 | bus_source: false 79 | bus_structure: null 80 | coordinate: [1784, 452.0] 81 | rotation: 0 82 | state: disabled 83 | - name: blocks_throttle_0 84 | id: blocks_throttle 85 | parameters: 86 | affinity: '' 87 | alias: '' 88 | comment: '' 89 | ignoretag: 'True' 90 | maxoutbuf: '0' 91 | minoutbuf: '0' 92 | samples_per_second: samp_rate 93 | type: complex 94 | vlen: '1' 95 | states: 96 | bus_sink: false 97 | bus_source: false 98 | bus_structure: null 99 | coordinate: [480, 300.0] 100 | rotation: 0 101 | state: true 102 | - name: inspector_qtgui_sink_vf_0 103 | id: inspector_qtgui_sink_vf 104 | parameters: 105 | affinity: '' 106 | alias: '' 107 | cfreq: '101669000' 108 | comment: '' 109 | fft_len: '4096' 110 | gui_hint: '' 111 | manual: 'False' 112 | maxoutbuf: '0' 113 | minoutbuf: '0' 114 | msgports: '1' 115 | rf_unit: '1' 116 | samp_rate: samp_rate 117 | states: 118 | bus_sink: false 119 | bus_source: false 120 | bus_structure: null 121 | coordinate: [1216, 352.0] 122 | rotation: 0 123 | state: enabled 124 | - name: inspector_signal_detector_cvf_0 125 | id: inspector_signal_detector_cvf 126 | parameters: 127 | affinity: '' 128 | alias: '' 129 | auto: 'False' 130 | avg: '0.2' 131 | comment: '' 132 | fft_len: '4096' 133 | logfile: '' 134 | maxoutbuf: '0' 135 | min_bw: '10000' 136 | minoutbuf: '0' 137 | quant: '0.001' 138 | samp_rate: samp_rate 139 | sensitivity: ' 0.2' 140 | threshold: thres 141 | window: window.WIN_BLACKMAN_hARRIS 142 | states: 143 | bus_sink: false 144 | bus_source: false 145 | bus_structure: null 146 | coordinate: [656, 352.0] 147 | rotation: 0 148 | state: enabled 149 | - name: soapy_rtlsdr_source_0 150 | id: soapy_rtlsdr_source 151 | parameters: 152 | affinity: '' 153 | agc: 'False' 154 | alias: '' 155 | center_freq: '101669000' 156 | comment: '' 157 | dev_args: '' 158 | freq_correction: '0' 159 | gain: '20' 160 | maxoutbuf: '0' 161 | minoutbuf: '0' 162 | samp_rate: '3200000' 163 | type: fc32 164 | states: 165 | bus_sink: false 166 | bus_source: false 167 | bus_structure: null 168 | coordinate: [112, 340.0] 169 | rotation: 0 170 | state: true 171 | 172 | connections: 173 | - [blocks_throttle_0, '0', inspector_signal_detector_cvf_0, '0'] 174 | - [inspector_qtgui_sink_vf_0, map_out, blocks_message_debug_0, print] 175 | - [inspector_signal_detector_cvf_0, '0', inspector_qtgui_sink_vf_0, '0'] 176 | - [inspector_signal_detector_cvf_0, map_out, inspector_qtgui_sink_vf_0, map_in] 177 | - [soapy_rtlsdr_source_0, '0', blocks_throttle_0, '0'] 178 | 179 | metadata: 180 | file_format: 1 181 | grc_version: v3.11.0.0git-73-ga44ffb7b 182 | -------------------------------------------------------------------------------- /examples/signal_detection.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | category: Custom 5 | cmake_opt: '' 6 | comment: '' 7 | copyright: '' 8 | description: '' 9 | gen_cmake: 'On' 10 | gen_linking: dynamic 11 | generate_options: qt_gui 12 | hier_block_src_path: '.:' 13 | id: signal_detection 14 | max_nouts: '0' 15 | output_language: python 16 | placement: (0,0) 17 | qt_qss_theme: '' 18 | realtime_scheduling: '' 19 | run: 'True' 20 | run_command: '{python} -u {filename}' 21 | run_options: prompt 22 | sizing_mode: fixed 23 | thread_safe_setters: '' 24 | title: '' 25 | window_size: '' 26 | states: 27 | bus_sink: false 28 | bus_source: false 29 | bus_structure: null 30 | coordinate: [8, 8] 31 | rotation: 0 32 | state: enabled 33 | 34 | blocks: 35 | - name: freq 36 | id: variable_qtgui_range 37 | parameters: 38 | comment: '' 39 | gui_hint: '' 40 | label: Frequency 41 | min_len: '200' 42 | orient: Qt.Horizontal 43 | rangeType: float 44 | start: '3200' 45 | step: '10' 46 | stop: '12700' 47 | value: '9800' 48 | widget: counter_slider 49 | states: 50 | bus_sink: false 51 | bus_source: false 52 | bus_structure: null 53 | coordinate: [316, 11] 54 | rotation: 0 55 | state: enabled 56 | - name: samp_rate 57 | id: variable 58 | parameters: 59 | comment: '' 60 | value: '32768' 61 | states: 62 | bus_sink: false 63 | bus_source: false 64 | bus_structure: null 65 | coordinate: [548, 11] 66 | rotation: 0 67 | state: enabled 68 | - name: analog_sig_source_x_0_0_0 69 | id: analog_sig_source_x 70 | parameters: 71 | affinity: '' 72 | alias: '' 73 | amp: '10' 74 | comment: '' 75 | freq: freq 76 | maxoutbuf: '0' 77 | minoutbuf: '0' 78 | offset: '0' 79 | phase: '0' 80 | samp_rate: samp_rate 81 | type: complex 82 | waveform: analog.GR_COS_WAVE 83 | states: 84 | bus_sink: false 85 | bus_source: false 86 | bus_structure: null 87 | coordinate: [66, 282] 88 | rotation: 0 89 | state: enabled 90 | - name: analog_sig_source_x_0_0_0_0 91 | id: analog_sig_source_x 92 | parameters: 93 | affinity: '' 94 | alias: '' 95 | amp: '10' 96 | comment: '' 97 | freq: '12700' 98 | maxoutbuf: '0' 99 | minoutbuf: '0' 100 | offset: '0' 101 | phase: '0' 102 | samp_rate: samp_rate 103 | type: complex 104 | waveform: analog.GR_COS_WAVE 105 | states: 106 | bus_sink: false 107 | bus_source: false 108 | bus_structure: null 109 | coordinate: [67, 493] 110 | rotation: 0 111 | state: enabled 112 | - name: analog_sig_source_x_0_0_0_1 113 | id: analog_sig_source_x 114 | parameters: 115 | affinity: '' 116 | alias: '' 117 | amp: '10' 118 | comment: '' 119 | freq: '3200' 120 | maxoutbuf: '0' 121 | minoutbuf: '0' 122 | offset: '0' 123 | phase: '0' 124 | samp_rate: samp_rate 125 | type: complex 126 | waveform: analog.GR_COS_WAVE 127 | states: 128 | bus_sink: false 129 | bus_source: false 130 | bus_structure: null 131 | coordinate: [71, 718] 132 | rotation: 0 133 | state: enabled 134 | - name: blocks_add_xx_0 135 | id: blocks_add_xx 136 | parameters: 137 | affinity: '' 138 | alias: '' 139 | comment: '' 140 | maxoutbuf: '0' 141 | minoutbuf: '0' 142 | num_inputs: '3' 143 | type: complex 144 | vlen: '1' 145 | states: 146 | bus_sink: false 147 | bus_source: false 148 | bus_structure: null 149 | coordinate: [510, 544] 150 | rotation: 0 151 | state: enabled 152 | - name: blocks_throttle_0 153 | id: blocks_throttle 154 | parameters: 155 | affinity: '' 156 | alias: '' 157 | comment: '' 158 | ignoretag: 'True' 159 | maxoutbuf: '0' 160 | minoutbuf: '0' 161 | samples_per_second: '10000000' 162 | type: complex 163 | vlen: '1' 164 | states: 165 | bus_sink: false 166 | bus_source: false 167 | bus_structure: null 168 | coordinate: [1116, 557] 169 | rotation: 0 170 | state: enabled 171 | - name: channels_channel_model_0 172 | id: channels_channel_model 173 | parameters: 174 | affinity: '' 175 | alias: '' 176 | block_tags: 'False' 177 | comment: '' 178 | epsilon: '1.0' 179 | freq_offset: '0.0' 180 | maxoutbuf: '0' 181 | minoutbuf: '0' 182 | noise_voltage: 10-4 183 | seed: '0' 184 | taps: 1.0 + 1.0j 185 | states: 186 | bus_sink: false 187 | bus_source: false 188 | bus_structure: null 189 | coordinate: [690, 492] 190 | rotation: 0 191 | state: enabled 192 | - name: inspector_qtgui_sink_vf_0 193 | id: inspector_qtgui_sink_vf 194 | parameters: 195 | affinity: '' 196 | alias: '' 197 | cfreq: '100000000' 198 | comment: '' 199 | fft_len: '4096' 200 | gui_hint: '' 201 | manual: 'False' 202 | maxoutbuf: '0' 203 | minoutbuf: '0' 204 | msgports: '1' 205 | rf_unit: '1' 206 | samp_rate: samp_rate 207 | states: 208 | bus_sink: false 209 | bus_source: false 210 | bus_structure: null 211 | coordinate: [2047, 492] 212 | rotation: 0 213 | state: enabled 214 | - name: inspector_signal_detector_cvf_0 215 | id: inspector_signal_detector_cvf 216 | parameters: 217 | affinity: '' 218 | alias: '' 219 | auto: 'False' 220 | avg: '0.2' 221 | comment: '' 222 | fft_len: '4096' 223 | logfile: '' 224 | maxoutbuf: '0' 225 | min_bw: '10' 226 | minoutbuf: '0' 227 | quant: '0.0001' 228 | samp_rate: samp_rate 229 | sensitivity: '0.9' 230 | threshold: '-20' 231 | window: window.WIN_BLACKMAN_hARRIS 232 | states: 233 | bus_sink: false 234 | bus_source: false 235 | bus_structure: null 236 | coordinate: [1490, 492] 237 | rotation: 0 238 | state: enabled 239 | 240 | connections: 241 | - [analog_sig_source_x_0_0_0, '0', blocks_add_xx_0, '0'] 242 | - [analog_sig_source_x_0_0_0_0, '0', blocks_add_xx_0, '1'] 243 | - [analog_sig_source_x_0_0_0_1, '0', blocks_add_xx_0, '2'] 244 | - [blocks_add_xx_0, '0', channels_channel_model_0, '0'] 245 | - [blocks_throttle_0, '0', inspector_signal_detector_cvf_0, '0'] 246 | - [channels_channel_model_0, '0', blocks_throttle_0, '0'] 247 | - [inspector_signal_detector_cvf_0, '0', inspector_qtgui_sink_vf_0, '0'] 248 | - [inspector_signal_detector_cvf_0, map_out, inspector_qtgui_sink_vf_0, map_in] 249 | 250 | metadata: 251 | file_format: 1 252 | -------------------------------------------------------------------------------- /grc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 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 | install(FILES 22 | inspector_ofdm_synchronizer_cc.block.yml 23 | inspector_ofdm_zkf_c.block.yml 24 | inspector_qtgui_inspector_sink_vf.block.yml 25 | inspector_signal_detector_cvf.block.yml 26 | inspector_signal_extractor_c.block.yml 27 | inspector_signal_separator_c.block.yml DESTINATION share/gnuradio/grc/blocks 28 | ) 29 | -------------------------------------------------------------------------------- /grc/inspector_ofdm_synchronizer_cc.block.yml: -------------------------------------------------------------------------------- 1 | id: inspector_ofdm_synchronizer_cc 2 | label: OFDM Synchronizer 3 | category: '[Inspector]/Conditioning' 4 | 5 | templates: 6 | imports: import gnuradio.inspector as inspector 7 | make: inspector.ofdm_synchronizer_cc(${min_items}) 8 | 9 | # Make one 'parameters' list entry for every Parameter you want settable from the GUI. 10 | # Sub-entries of dictionary: 11 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 12 | # * label 13 | # * dtype 14 | parameters: 15 | - id: min_items 16 | label: Min input items 17 | default: 4096 18 | dtype: int 19 | 20 | # Make one 'inputs' list entry per input. Sub-entries of dictionary: 21 | # * label (an identifier for the GUI) 22 | # * domain 23 | # * dtype 24 | # * vlen 25 | # * optional (set to 1 for optional inputs) 26 | inputs: 27 | - domain: stream 28 | dtype: complex 29 | - label: ofdm_in 30 | domain: message 31 | 32 | # Make one 'outputs' list entry per output. Sub-entries of dictionary: 33 | # * label (an identifier for the GUI) 34 | # * dtype 35 | # * vlen 36 | # * optional (set to 1 for optional inputs) 37 | outputs: 38 | - domain: stream 39 | dtype: complex 40 | 41 | file_format: 1 42 | -------------------------------------------------------------------------------- /grc/inspector_ofdm_zkf_c.block.yml: -------------------------------------------------------------------------------- 1 | id: inspector_ofdm_zkf_c 2 | label: OFDM Estimator 3 | category: '[Inspector]/Analysis' 4 | 5 | templates: 6 | imports: import gnuradio.inspector as inspector 7 | make: inspector.ofdm_zkf_c(${samp_rate}, ${signal}, ${min_items}, ${alpha}, ${beta}) 8 | 9 | # Make one 'parameters' list entry for every Parameter you want settable from the GUI. 10 | # Sub-entries of dictionary: 11 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 12 | # * label 13 | # * dtype 14 | parameters: 15 | - id: samp_rate 16 | label: Sample rate 17 | dtype: real 18 | - id: signal 19 | label: Signal No 20 | dtype: int 21 | default: 0 22 | - id: min_items 23 | label: Min input items 24 | dtype: int 25 | default: 7000 26 | - id: alpha 27 | label: FFT lengths 28 | dtype: int_vector 29 | default: [16, 32, 64, 128, 256, 512, 1024] 30 | - id: beta 31 | label: CP lengths 32 | dtype: int_vector 33 | default: [4, 8, 16, 32] 34 | 35 | # Make one 'inputs' list entry per input. Sub-entries of dictionary: 36 | # * label (an identifier for the GUI) 37 | # * domain 38 | # * dtype 39 | # * vlen 40 | # * optional (set to 1 for optional inputs) 41 | inputs: 42 | - label: in 43 | domain: stream 44 | dtype: complex 45 | 46 | # Make one 'outputs' list entry per output. Sub-entries of dictionary: 47 | # * label (an identifier for the GUI) 48 | # * dtype 49 | # * vlen 50 | # * optional (set to 1 for optional inputs) 51 | outputs: 52 | - label: ofdm_out 53 | domain: message 54 | 55 | file_format: 1 56 | -------------------------------------------------------------------------------- /grc/inspector_qtgui_inspector_sink_vf.block.yml: -------------------------------------------------------------------------------- 1 | id: inspector_qtgui_sink_vf 2 | label: QT GUI Inspector Sink 3 | category: '[Inspector]/GUI' 4 | 5 | templates: 6 | imports: |- 7 | import gnuradio.inspector as inspector 8 | from PyQt5 import Qt 9 | from gnuradio import qtgui 10 | import sip 11 | 12 | callbacks: 13 | - set_rf_unit(${rf_unit}) 14 | - set_cfreq(${cfreq}) 15 | - set_samp_rate(${samp_rate}) 16 | 17 | make: |- 18 | <% 19 | win = 'self._%s_win'%id 20 | %>\ 21 | inspector.qtgui_inspector_sink_vf( 22 | ${samp_rate}, 23 | ${fft_len}, 24 | ${cfreq}, 25 | ${rf_unit}, 26 | ${msgports}, 27 | ${manual} 28 | ) 29 | ${win} = sip.wrapinstance(self.${id}.pyqwidget(), Qt.QWidget) 30 | 31 | ${gui_hint() % win} 32 | 33 | # Make one 'parameters' list entry for every Parameter you want settable from the GUI. 34 | # Sub-entries of dictionary: 35 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 36 | # * label 37 | # * dtype 38 | parameters: 39 | - id: samp_rate 40 | label: Samp Rate 41 | dtype: real 42 | - id: fft_len 43 | label: FFT len 44 | dtype: int 45 | - id: cfreq 46 | label: Center freq 47 | dtype: real 48 | default: 0 49 | - id: rf_unit 50 | label: Rf Unit 51 | dtype: enum 52 | default: 1000000 53 | options: [1, 1000, 1000000, 1000000000] 54 | option_labels: ['Hz', 'kHz', 'MHz', 'GHz'] 55 | - id: msgports 56 | label: No. of MSG ports 57 | dtype: int 58 | default: 1 59 | - id: manual 60 | label: Manual selection 61 | dtype: bool 62 | default: True 63 | - id: gui_hint 64 | label: GUI Hint 65 | dtype: gui_hint 66 | default: '' 67 | 68 | # Make one 'inputs' list entry per input. Sub-entries of dictionary: 69 | # * label (an identifier for the GUI) 70 | # * domain 71 | # * dtype 72 | # * vlen 73 | # * optional (set to 1 for optional inputs) 74 | inputs: 75 | - label: in 76 | domain: stream 77 | dtype: float 78 | vlen: ${fft_len} 79 | - label: map_in 80 | domain: message 81 | - label: analysis_in 82 | domain: message 83 | multiplicity: ${msgports} 84 | optional: True 85 | 86 | # Make one 'outputs' list entry per output. Sub-entries of dictionary: 87 | # * label (an identifier for the GUI) 88 | # * dtype 89 | # * vlen 90 | # * optional (set to 1 for optional inputs) 91 | outputs: 92 | - label: map_out 93 | domain: message 94 | optional: True 95 | 96 | documentation: |- 97 | This GUI uses QT and QWT to create a graphical interface to control the inspector and get feedback about the detected and analyzed signals. 98 | 99 | The PSD estimation of the Signal Detector block gets displayed here along with signal markers and informations. Manual signal selection can be done within the GUI created by this block. 100 | 101 | Analysis blocks can pass information to the GUI block by providing messages in the tuple format 102 | 103 | ((pmt::intern("signal"), signal_no), (pmt::intern("description1"), pmt::from_float(value1)), ...) 104 | 105 | Controls: Use CTRL+LeftMouse to zoom, RightMouse to zoom out. This prevents confusion when in manual selection mode, where the signals are selected with LeftMouse. 106 | 107 | Message ports: 108 | - map in: takes RF map from Signal Detector block and visualizes the included information in the plot 109 | - analysis_in: takes messages of analysis blocks and displays their content in the GUI plot. 110 | - map out: passes either the input message when manual selection is deactivated or passes RF map according to the user's settings. 111 | 112 | 113 | file_format: 1 114 | -------------------------------------------------------------------------------- /grc/inspector_signal_detector_cvf.block.yml: -------------------------------------------------------------------------------- 1 | id: inspector_signal_detector_cvf 2 | label: Signal Detector 3 | category: '[Inspector]/Conditioning' 4 | 5 | templates: 6 | imports: import gnuradio.inspector as inspector 7 | make: inspector.signal_detector_cvf(${samp_rate}, ${fft_len}, ${window}, ${threshold}, ${sensitivity}, ${auto}, ${avg}, ${quant}, ${min_bw}, ${logfile}) 8 | callbacks: 9 | - set_fft_len(${fft_len}) 10 | - set_window_type(${window}) 11 | - set_samp_rate(${samp_rate}) 12 | - set_sensitivity(${sensitivity}) 13 | - set_auto_threshold({$auto}) 14 | - set_average({$avg}) 15 | - set_quantization({$quant}) 16 | - set_threshold(${threshold}) 17 | 18 | # Make one 'parameters' list entry for every Parameter you want settable from the GUI. 19 | # Sub-entries of dictionary: 20 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 21 | # * label 22 | # * dtype 23 | parameters: 24 | - id: samp_rate 25 | label: Samp rate 26 | dtype: real 27 | - id: fft_len 28 | label: FFT length 29 | dtype: int 30 | default: 1024 31 | - id: window 32 | label: Window 33 | dtype: enum 34 | options: [window.WIN_BLACKMAN_hARRIS, window.WIN_HAMMING, window.WIN_HANN, window.WIN_BLACKMAN, window.WIN_RECTANGULAR, window.WIN_KAISER, window.WIN_FLATTOP] 35 | option_labels: ['Blackman-Harris', 'Hamming', 'Hann', 'Blackman', 'Rectangular', 'Kaiser', 'Flat-top'] 36 | default: window.WIN_BLACKMAN_hARRIS 37 | - id: auto 38 | label: Auto threshold 39 | dtype: bool 40 | default: True 41 | - id: threshold 42 | label: Threshold (dB) 43 | dtype: float 44 | default: 0.7 45 | hide: ${('all' if auto else 'none')} 46 | - id: sensitivity 47 | label: Sensitivity (0-1) 48 | dtype: float 49 | default: 0.2 50 | hide: ${('none' if auto else 'all')} 51 | - id: avg 52 | label: Average IIR alpha 53 | dtype: real 54 | default: 0.8 55 | - id: quant 56 | label: Rel. quantization 57 | dtype: real 58 | default: 0.0001 59 | hide: 'part' 60 | - id: min_bw 61 | label: Min Sig BW 62 | dtype: real 63 | default: 0 64 | hide: 'part' 65 | - id: logfile 66 | label: Logfile 67 | dtype: file_save 68 | default: '' 69 | hide: 'part' 70 | 71 | # Make one 'inputs' list entry per input. Sub-entries of dictionary: 72 | # * label (an identifier for the GUI) 73 | # * domain 74 | # * dtype 75 | # * vlen 76 | # * optional (set to 1 for optional inputs) 77 | inputs: 78 | - label: in 79 | domain: stream 80 | dtype: complex 81 | 82 | # Make one 'outputs' list entry per output. Sub-entries of dictionary: 83 | # * label (an identifier for the GUI) 84 | # * dtype 85 | # * vlen 86 | # * optional (set to 1 for optional inputs) 87 | outputs: 88 | - label: out 89 | domain: stream 90 | dtype: float 91 | vlen: ${fft_len} 92 | optional: true 93 | - label: map_out 94 | domain: message 95 | optional: true 96 | 97 | file_format: 1 98 | -------------------------------------------------------------------------------- /grc/inspector_signal_extractor_c.block.yml: -------------------------------------------------------------------------------- 1 | id: inspector_signal_extractor_c 2 | label: Signal Extractor 3 | category: '[Inspector]/Conditioning' 4 | 5 | templates: 6 | imports: import gnuradio.inspector as inspector 7 | make: inspector.signal_extractor_c(${signal}, ${resample}, ${rate}, ${osf}) 8 | callbacks: 9 | - set_signal(${signal}) 10 | 11 | # Make one 'parameters' list entry for every Parameter you want settable from the GUI. 12 | # Sub-entries of dictionary: 13 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 14 | # * label 15 | # * dtype 16 | parameters: 17 | - id: signal 18 | label: Signal 19 | dtype: int 20 | - id: resample 21 | label: Resample signal 22 | dtype: bool 23 | default: False 24 | options: [True, False] 25 | option_labels: ['On', 'Off'] 26 | - id: rate 27 | label: Output samp rate 28 | dtype: real 29 | default: 48000 30 | hide: ${('none' if resample else 'all')} 31 | - id: osf 32 | label: Oversampling 33 | dtype: real 34 | default: 1 35 | hide: ${('none' if resample else 'all')} 36 | 37 | # Make one 'inputs' list entry per input. Sub-entries of dictionary: 38 | # * label (an identifier for the GUI) 39 | # * domain 40 | # * dtype 41 | # * vlen 42 | # * optional (set to 1 for optional inputs) 43 | inputs: 44 | - label: sig_in 45 | domain: message 46 | 47 | # Make one 'outputs' list entry per output. Sub-entries of dictionary: 48 | # * label (an identifier for the GUI) 49 | # * dtype 50 | # * vlen 51 | # * optional (set to 1 for optional inputs) 52 | outputs: 53 | - label: out 54 | domain: stream 55 | dtype: complex 56 | 57 | file_format: 1 58 | -------------------------------------------------------------------------------- /grc/inspector_signal_separator_c.block.yml: -------------------------------------------------------------------------------- 1 | id: inspector_signal_separator_c 2 | label: Signal Separator 3 | category: '[Inspector]/Conditioning' 4 | 5 | templates: 6 | imports: |- 7 | import gnuradio.inspector as inspector 8 | from gnuradio.filter import firdes 9 | import json 10 | make: |- 11 | inspector.signal_separator_c(${samp_rate}, ${window}, ${trans_width}, ${oversample}, ${file}, {int(k):v for k,v in json.loads(open(${taps_file}).read())}) \ 12 | if ${file} else \ 13 | inspector.signal_separator_c(${samp_rate}, ${window}, ${trans_width}, ${oversample}, ${file}, {0:[0]}) 14 | callbacks: 15 | - set_samp_rate(${samp_rate}) 16 | - set_window(${window}) 17 | - set_trans_width(${trans_width}) 18 | - set oversampling(${oversample}) 19 | 20 | # Make one 'parameters' list entry for every Parameter you want settable from the GUI. 21 | # Sub-entries of dictionary: 22 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 23 | # * label 24 | # * dtype 25 | parameters: 26 | - id: samp_rate 27 | label: Samp rate 28 | dtype: real 29 | - id: trans_width 30 | label: Trans. width/cutoff 31 | dtype: real 32 | - id: window 33 | label: Window 34 | dtype: enum 35 | options: [window.WIN_BLACKMAN_hARRIS, window.WIN_HAMMING, window.WIN_HANN, window.WIN_BLACKMAN, window.WIN_RECTANGULAR, window.WIN_KAISER, window.WIN_FLATTOP] 36 | option_labels: ['Blackman-Harris', 'Hamming', 'Hann', 'Blackman', 'Rectangular', 'Kaiser', 'Flat-top'] 37 | default: window.WIN_BLACKMAN_hARRIS 38 | - id: oversample 39 | label: Oversampling 40 | dtype: real 41 | - id: file 42 | label: Use Taps file 43 | dtype: bool 44 | default: True 45 | - id: taps_file 46 | label: Taps file 47 | default: '' 48 | dtype: file_open 49 | hide: ${('none' if file else 'all')} 50 | 51 | # Make one 'inputs' list entry per input. Sub-entries of dictionary: 52 | # * label (an identifier for the GUI) 53 | # * domain 54 | # * dtype 55 | # * vlen 56 | # * optional (set to 1 for optional inputs) 57 | inputs: 58 | - label: in 59 | domain: stream 60 | dtype: complex 61 | - label: map_in 62 | domain: message 63 | 64 | # Make one 'outputs' list entry per output. Sub-entries of dictionary: 65 | # * label (an identifier for the GUI) 66 | # * dtype 67 | # * vlen 68 | # * optional (set to 1 for optional inputs) 69 | outputs: 70 | - label: sig_out 71 | domain: message 72 | 73 | file_format: 1 74 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Install public header files 11 | ######################################################################## 12 | install(FILES 13 | api.h 14 | inspector_form.h 15 | signal_marker.h 16 | ofdm_synchronizer_cc.h 17 | ofdm_bouzegzi_c.h 18 | ofdm_zkf_c.h 19 | qtgui_inspector_sink_vf.h 20 | signal_detector_cvf.h 21 | signal_extractor_c.h 22 | signal_separator_c.h 23 | DESTINATION include/gnuradio/inspector 24 | ) 25 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Free Software Foundation, Inc. 3 | * 4 | * This file was generated by gr_modtool, a tool from the GNU Radio framework 5 | * This file is a part of gr-inspector 6 | * 7 | * SPDX-License-Identifier: GPL-3.0-or-later 8 | * 9 | */ 10 | 11 | #ifndef INCLUDED_INSPECTOR_API_H 12 | #define INCLUDED_INSPECTOR_API_H 13 | 14 | #include 15 | 16 | #ifdef gnuradio_inspector_EXPORTS 17 | #define INSPECTOR_API __GR_ATTR_EXPORT 18 | #else 19 | #define INSPECTOR_API __GR_ATTR_IMPORT 20 | #endif 21 | 22 | #endif /* INCLUDED_INSPECTOR_API_H */ 23 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/inspector_form.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef GR_INSPECTOR_INSPECTOR_SINK_H 22 | #define GR_INSPECTOR_INSPECTOR_SINK_H 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "signal_marker.h" 39 | 40 | namespace gr { 41 | namespace inspector { 42 | 43 | class Zoomer : public QwtPlotZoomer 44 | { 45 | public: 46 | Zoomer(int xAxis, int yAxis, QWidget* canvas) : QwtPlotZoomer(xAxis, yAxis, canvas) 47 | { 48 | // setSelectionFlags(QwtPicker::DragSelection | QwtPicker::CornerToCorner); 49 | setTrackerMode(QwtPicker::AlwaysOn); 50 | setRubberBand(QwtPicker::RectRubberBand); 51 | QPen pen = 52 | QPen(QColor(100, 100, 100), 1, Qt::DashLine, Qt::RoundCap, Qt::RoundJoin); 53 | setTrackerPen(pen); 54 | setRubberBandPen(pen); 55 | 56 | // RightButton: zoom out by 1 57 | // Ctrl+RightButton: zoom out to full size 58 | 59 | #if QT_VERSION < 0x040000 60 | setMousePattern( 61 | QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlButton); 62 | #else 63 | setMousePattern( 64 | QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier); 65 | #endif 66 | setMousePattern(QwtEventPattern::MouseSelect3, Qt::RightButton); 67 | setMousePattern( 68 | QwtEventPattern::MouseSelect1, Qt::LeftButton, Qt::ControlModifier); 69 | } 70 | }; 71 | 72 | class inspector_form : public QWidget 73 | { 74 | Q_OBJECT 75 | 76 | public: 77 | void set_axis_x(float start, float stop); 78 | void msg_received(); 79 | void set_cfreq(float freq); 80 | void detach_markers(); 81 | void mousePressEvent(QMouseEvent* eventPress); 82 | void mouseReleaseEvent(QMouseEvent* eventRelease); 83 | void mouseMoveEvent(QMouseEvent* eventMove); 84 | void spawn_signal_selector(); 85 | void add_msg_queue(float cfreq, float bandwidth); 86 | float freq_to_x(float freq); 87 | float x_to_freq(float x); 88 | void add_analysis_text(int signal, std::string text); 89 | 90 | void drawOverlay(); 91 | void draw_analysis_text(); 92 | inspector_form(int fft_len, 93 | std::vector* buffer, 94 | std::vector>* rf_map, 95 | bool* manual, 96 | gr::msg_queue* msg_queue, 97 | int* rf_unit, 98 | QWidget* parent); 99 | ~inspector_form(); 100 | 101 | private: 102 | enum markerType { NONE, LEFT, CENTER, RIGHT }; 103 | 104 | bool change_flag; 105 | int d_interval, d_fft_len, d_marker_count; 106 | int* d_rf_unit; 107 | bool* d_manual; 108 | std::vector d_axis_x, d_axis_y; 109 | std::vector* d_buffer; 110 | float d_max, d_min, d_cfreq, d_mouse_offset; 111 | double* d_freq; 112 | std::map d_analysis_texts; 113 | std::vector>* d_rf_map; 114 | markerType d_clicked_marker; 115 | QList d_markers; 116 | QwtSymbol* d_symbol; 117 | Zoomer* d_zoomer; 118 | QwtPlot* d_plot; 119 | QwtScaleWidget* d_scale; 120 | QwtPlotCurve* d_curve; 121 | QTimer* d_timer; 122 | QwtPlotGrid* d_grid; 123 | QGridLayout* d_layout; 124 | 125 | QCheckBox* d_manual_cb; 126 | gr::msg_queue* d_msg_queue; 127 | 128 | gr::thread::mutex d_mutex; 129 | 130 | protected: 131 | void resizeEvent(QResizeEvent* event); 132 | 133 | public slots: 134 | void refresh(); 135 | void manual_cb_clicked(int state); 136 | }; 137 | 138 | 139 | } // namespace inspector 140 | } // namespace gr 141 | 142 | #endif // GR_INSPECTOR_INSPECTOR_SINK_H 143 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/ofdm_bouzegzi_c.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_OFDM_BOUZEGZI_C_H 22 | #define INCLUDED_INSPECTOR_OFDM_BOUZEGZI_C_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | /*! 31 | * \brief OFDM parameter estimator (Bouzegzi algorithm) 32 | * \ingroup inspector 33 | * 34 | * \details 35 | * This block was not further developed during GSoC since 36 | * real-time estimation was not possible. 37 | */ 38 | class INSPECTOR_API ofdm_bouzegzi_c : virtual public gr::sync_block 39 | { 40 | public: 41 | typedef std::shared_ptr sptr; 42 | 43 | /*! 44 | * \brief Return a shared_ptr to a new instance of inspector::ofdm_bouzegzi_c. 45 | * 46 | * To avoid accidental use of raw pointers, inspector::ofdm_bouzegzi_c's 47 | * constructor is in a private implementation 48 | * class. inspector::ofdm_bouzegzi_c::make is the public interface for 49 | * creating new instances. 50 | */ 51 | static sptr make(double samp_rate, 52 | int Nb, 53 | const std::vector& alpha, 54 | const std::vector& beta); 55 | }; 56 | 57 | } // namespace inspector 58 | } // namespace gr 59 | 60 | #endif /* INCLUDED_INSPECTOR_OFDM_BOUZEGZI_C_H */ 61 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/ofdm_synchronizer_cc.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_OFDM_SYNCHRONIZER_CC_H 22 | #define INCLUDED_INSPECTOR_OFDM_SYNCHRONIZER_CC_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | /*! 31 | * \brief OFDM frequency synchronizer and timing estimator 32 | * \ingroup inspector 33 | * 34 | * \details 35 | * This block can be inserted downstream to the OFDM parameter 36 | * estimation block. It performs a frequency offset estimation and 37 | * symbol timing estimation according to [1]. Frequency offsets smaller than the 38 | * subcarrier spacing will be corrected to obtain orthogonality of 39 | * the carriers. Output is a stream with stream tags at the estimated 40 | * OFDM symbol beginnings (PMT symbol "symbol"). 41 | * 42 | * Connect output of OFDM parameter estimator to message port and 43 | * signal itself to the stream input. 44 | * 45 | * [1] J. J. van de Beek, M. Sandell, and P. O. Borjesson, 46 | * “ML estimation of time and frequency offset in OFDM systems,” 47 | * IEEE Transactions on Signal Processing, vol. 45, no. 7, pp. 48 | * 1800–1805, 1997. [Online]. Available: 49 | * http://pure.ltu.se/portal/files/1612155/Article.pdf. 50 | */ 51 | class INSPECTOR_API ofdm_synchronizer_cc : virtual public gr::sync_block 52 | { 53 | public: 54 | typedef std::shared_ptr sptr; 55 | 56 | /*! 57 | * \brief Return a shared_ptr to a new instance of inspector::ofdm_synchronizer_cc. 58 | * 59 | * To avoid accidental use of raw pointers, inspector::ofdm_synchronizer_cc's 60 | * constructor is in a private implementation 61 | * class. inspector::ofdm_synchronizer_cc::make is the public interface for 62 | * creating new instances. 63 | * 64 | * \param min_items Set minimum items required for each work call. Should be several 65 | * FFT lengths. 66 | */ 67 | static sptr make(int min_items); 68 | }; 69 | 70 | } // namespace inspector 71 | } // namespace gr 72 | 73 | #endif /* INCLUDED_INSPECTOR_OFDM_SYNCHRONIZER_CC_H */ 74 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/ofdm_zkf_c.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_OFDM_ZKF_C_H 22 | #define INCLUDED_INSPECTOR_OFDM_ZKF_C_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | /*! 31 | * \brief Parameter estimation block for OFDM signals 32 | * \ingroup inspector 33 | * 34 | * \details 35 | * This block performs a parameter estimation of an input OFDM signal. 36 | * Parameters that get estimated are FFT length, cyclic prefix length, 37 | * symbol time and subcarrier spacing. For the estimation, the algorithm 38 | * in [1] is used. Input is a complex stream, output is a message as 39 | * tupel of tupels containing analysis results description and values. 40 | * 41 | * [1] S. Koslowski, "Implementierung eines OFDM-Merkmalsklassifikators in einer 42 | * SCA-Umgebung," Diploma Thesis, Karlsruhe Institute of Technology, 2011. 43 | */ 44 | class INSPECTOR_API ofdm_zkf_c : virtual public gr::sync_block 45 | { 46 | public: 47 | typedef std::shared_ptr sptr; 48 | 49 | /*! 50 | * \brief Return a shared_ptr to a new instance of inspector::ofdm_zkf_c. 51 | * 52 | * \param samp_rate The samples rate of the input signal 53 | * \param signal The number of the analyzed signal 54 | * \param min_items Set minimum items required for each work call. Should be several 55 | * FFT lengths. \param typ_len Typical FFT lengths to search for. Can also be set to a 56 | * fine grid when no knowledge about the signal is present. \param typ_cp Typical 57 | * cyclic prefix lengths to search for. Can also be set to a fine grid when no 58 | * knowledge about the signal is present. 59 | */ 60 | static sptr make(double samp_rate, 61 | int signal, 62 | int min_items, 63 | const std::vector& typ_len, 64 | const std::vector& typ_cp); 65 | virtual void set_samp_rate(double d_samp_rate) = 0; 66 | }; 67 | 68 | } // namespace inspector 69 | } // namespace gr 70 | 71 | #endif /* INCLUDED_INSPECTOR_OFDM_ZKF_C_H */ 72 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/qtgui_inspector_sink_vf.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_QTGUI_INSPECTOR_SINK_VF_H 22 | #define INCLUDED_INSPECTOR_QTGUI_INSPECTOR_SINK_VF_H 23 | 24 | #ifdef ENABLE_PYTHON 25 | #include 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | namespace gr { 33 | namespace inspector { 34 | 35 | /*! 36 | * \brief GUI for the inspector toolkit 37 | * \ingroup inspector 38 | * 39 | * \details 40 | * This GUI uses QT and QWT to create a graphical interface to control the 41 | * inspector and get feedback about the detected and analyzed signals. 42 | * 43 | * The PSD estimation of the Signal Detector block gets displayed here along 44 | * with signal markers and informations. Manual signal selection can be done 45 | * within the GUI created by this block. 46 | * 47 | * Analysis blocks can pass information to the GUI block by providing 48 | * messages in the tuple format 49 | * 50 | * ((pmt::intern("signal"), pmt::from_uint64(signal_no)), 51 | * (pmt::intern("description1"), pmt::from_float(value1)), ...) 52 | * 53 | * Controls: Use CTRL+LeftMouse to zoom, RightMouse to zoom out. 54 | * This prevents confusion when in manual selection mode, where the 55 | * signals are selected with LeftMouse. 56 | * 57 | * Message ports: 58 | * - map in: takes RF map from Signal Detector block and visualizes the included 59 | * information in the plot 60 | * - analysis_in: takes messages of analysis blocks and displays their content 61 | * in the GUI plot. 62 | * - map out: passes either the input message when manual selection is deactivated 63 | * or passes RF map according to the user's manual settings. 64 | */ 65 | class INSPECTOR_API qtgui_inspector_sink_vf : virtual public gr::sync_block 66 | { 67 | public: 68 | typedef std::shared_ptr sptr; 69 | 70 | /*! 71 | * \brief Build a GUI sink instance. 72 | * 73 | * \param samp_rate Sample rate of the input signal. 74 | * \param fft_len Vector input size and number of PSD sample points 75 | * \param cfreq Center frequency of source. Set to 0 if only relative frequencies are 76 | * desired downstream. \param rf_unit Determine which unit the GUI uses to display 77 | * frequencies \param msgports Number of message ports for analysis feedback \param 78 | * manual Enable manual signal selection \param parent QWidget parent 79 | */ 80 | static sptr make(double samp_rate, 81 | int fft_len, 82 | float cfreq = 0, 83 | int rf_unit = 1000000, 84 | int msgports = 1, 85 | bool manual = false, 86 | QWidget* parent = nullptr); 87 | virtual void set_rf_unit(int unit) = 0; 88 | virtual void set_samp_rate(double d_samp_rate) = 0; 89 | virtual void set_cfreq(float cfreq) = 0; 90 | #ifdef ENABLE_PYTHON 91 | virtual PyObject* pyqwidget() = 0; 92 | #else 93 | virtual void* pyqwidget() = 0; 94 | #endif 95 | }; 96 | 97 | } // namespace inspector 98 | } // namespace gr 99 | 100 | #endif /* INCLUDED_INSPECTOR_QTGUI_INSPECTOR_SINK_VF_H */ 101 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/signal_detector_cvf.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_SIGNAL_DETECTOR_CVF_H 22 | #define INCLUDED_INSPECTOR_SIGNAL_DETECTOR_CVF_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | /*! 31 | * \brief Signal detection block using energy detection. 32 | * \ingroup inspector 33 | * 34 | * \details 35 | * Takes input spectrum as complex float and performs an energy detection 36 | * to find potential continuous signals and build a RF map (tuple 37 | * of center frequency and bandwidth). The RF map gets passed as a 38 | * message with center frequency and bandwidth information for each detected 39 | * signal. 40 | * 41 | * Threshold for energy detection can either be set in dB or an automatic 42 | * threshold calculation can be performed by setting a sensitivity between 0 43 | * and 1. The PSD is then sorted and searched for relative power jumps with height 44 | * (1-sensitivity) and the threshold is set to the sample before that jump 45 | * (which should be the strongest noise sample). 46 | * 47 | * To surpress false detection in noisy scenarios, the minimum signal bandwidth 48 | * can be set. All detected signals smaller than this value will not be written 49 | * in the RF map. 50 | * 51 | * To average the PSD (and provide a better detection) an single pole IIR 52 | * filter is implemented in this block. The parameter alpha can be set as 53 | * block parameter. The IIR equation yields y[n] = alpha*x[n]+(1-alpha)*y[n-1]. 54 | * 55 | * The bandwidth of the detected signals can be quantized relative to the 56 | * sampling rate. This leads to less recalculations in the Signal Separator 57 | * block. There, a filter must be recalculated, when the bandwidth of a signal 58 | * changed. 59 | */ 60 | class INSPECTOR_API signal_detector_cvf : virtual public gr::sync_decimator 61 | { 62 | public: 63 | typedef std::shared_ptr sptr; 64 | 65 | /*! 66 | * \brief Return a signal detector block instance. 67 | * 68 | * \param samp_rate Sample rate of the input signal 69 | * \param fft_len Desired number of FFT points for the PSD. Also sets the input items 70 | * consumed in evry work cycle. \param window_type Firdes window type to scale the 71 | * input samples with \param threshold Threshold in dB for energy detection when 72 | * automatic signal detection is disabled \param sensitivity Sensitivity value between 73 | * 0 and 1 if automatic signal detection is enabled \param auto_threshold Bool to set 74 | * automatic threshold calculation \param average Averaging factor in (0,1] (equal to 75 | * alpha in IIR equation) \param quantization Bandwidth quantization yields 76 | * quantization*samp_rate [Hz] \param min_bw Minimum signal bandwidth. Don't pass any 77 | * narrower signals. \param filename Path to a file where the detections are logged. 78 | * Leave empty for no log. 79 | */ 80 | static sptr make(double samp_rate, 81 | int fft_len = 1024, 82 | int window_type = 0, 83 | float threshold = 0.7, 84 | float sensitivity = 0.2, 85 | bool auto_threshold = true, 86 | float average = 0.8, 87 | float quantization = 0.01, 88 | float min_bw = 0.0, 89 | const char* filename = ""); 90 | 91 | virtual void set_samp_rate(double d_samp_rate) = 0; 92 | virtual void set_fft_len(int fft_len) = 0; 93 | 94 | /*! 95 | * Takes integers and does internal cast to firdes::win_type 96 | */ 97 | virtual void set_window_type(int d_window) = 0; 98 | 99 | virtual void set_threshold(float d_threshold) = 0; 100 | virtual void set_sensitivity(float d_sensitivity) = 0; 101 | virtual void set_auto_threshold(bool d_auto_threshold) = 0; 102 | virtual void set_average(float d_average) = 0; 103 | }; 104 | 105 | } // namespace inspector 106 | } // namespace gr 107 | 108 | #endif /* INCLUDED_INSPECTOR_SIGNAL_DETECTOR_CVF_H */ 109 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/signal_extractor_c.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_SIGNAL_EXTRACTOR_C_H 22 | #define INCLUDED_INSPECTOR_SIGNAL_EXTRACTOR_C_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | /*! 31 | * \brief Extractor block to extract signal samples out of bundled message passed from 32 | * Signal Separator block. \ingroup inspector 33 | * 34 | * \details 35 | * Signal Extractor block is able to extract signal samples for specified 36 | * signal out of message passed by Signal Separator block. These messages 37 | * contain the samples of all detected signals. This block only passes the 38 | * ones beloging to the specified signal number as a complex stream. This 39 | * way, custom signal chains can be appended after the inspector blocks. 40 | * 41 | * If the resample option is used, the block will try to resample the 42 | * input samples based on the message input from the map port to the 43 | * desired output sample rate. An oversampling factor can be taken 44 | * into account, if the input samples are oversampled by the 45 | * signal separator. 46 | */ 47 | class INSPECTOR_API signal_extractor_c : virtual public gr::sync_block 48 | { 49 | public: 50 | typedef std::shared_ptr sptr; 51 | 52 | /*! 53 | * \brief Return a new Extractor block instance 54 | * 55 | * \param signal Output Signal number (beginning with 0) for desired sample 56 | * \param resample Enable resampling of samples 57 | * \param rate Desired output sample rate if resample is enabled 58 | * \param osf Oversampling factor of the input signal (relative to map input) 59 | */ 60 | static sptr 61 | make(int signal, bool resample = false, float rate = 1.0, float osf = 1.0); 62 | virtual void set_signal(int signal) = 0; 63 | }; 64 | 65 | } // namespace inspector 66 | } // namespace gr 67 | 68 | #endif /* INCLUDED_INSPECTOR_SIGNAL_EXTRACTOR_C_H */ 69 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/signal_marker.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef GR_INSPECTOR_SIGNAL_MARKER_H 22 | #define GR_INSPECTOR_SIGNAL_MARKER_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | namespace gr { 29 | namespace inspector { 30 | 31 | class signal_marker 32 | { 33 | private: 34 | public: 35 | QwtPlotMarker* d_center; 36 | QwtPlotMarker* d_label; 37 | QwtPlotZoneItem* d_zone; 38 | QwtPlot* d_plot; 39 | float d_freq, d_bw; 40 | int d_number, d_unit; 41 | QString d_unittxt; 42 | 43 | signal_marker(int i, QwtPlot* plot); 44 | 45 | ~signal_marker(); 46 | 47 | void add_text(std::string text); 48 | void set_label_y(qreal yval); 49 | void set_marker(int i, float center, float bw, int unit); 50 | QString basic_text(); 51 | void set_label_text(QString qstring); 52 | }; 53 | 54 | } // namespace inspector 55 | } // namespace gr 56 | 57 | #endif // GR_INSPECTOR_SIGNAL_MARKER_H 58 | -------------------------------------------------------------------------------- /include/gnuradio/inspector/signal_separator_c.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_SIGNAL_SEPARATOR_C_H 22 | #define INCLUDED_INSPECTOR_SIGNAL_SEPARATOR_C_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | /*! 31 | * \brief Signal Separator takes input signal and RF map as input and passes samples of 32 | * each filtered and decimated signal as output \ingroup inspector 33 | * 34 | * \details 35 | * Signal Separator block takes input signal and RF map with signal center 36 | * frequencies and bandwidths and filters the input spectrum for each signal. 37 | * 38 | * Internally, FIR filters get calculated according to the RF map's specs. 39 | * The steepness of the filters can be set with the relative transition width parameter. 40 | * The spectrum gets shifted by the center frequency of each signal and filtered 41 | * with the corresponding filter calculated from the RF map information. A floored integer 42 | * decimation will be applied according to the set oversampling factor 43 | * (decim = floor(samp_rate/(bw*OSF))). 44 | * 45 | * To save CPU load, generic taps can be precalculated with the tool in the apps/ 46 | * folder. This tool outputs a JSON file, which path can be specified in the block 47 | * parameter file_path. 48 | * 49 | * Output of this block is a pmt vector of tuples in the format 50 | * 51 | * #[#(SigNo, cfreq, bandwidth, #[vector of samples]), #(...)] 52 | */ 53 | class INSPECTOR_API signal_separator_c : virtual public gr::block 54 | { 55 | public: 56 | typedef std::shared_ptr sptr; 57 | 58 | /*! 59 | * \brief Return new instance of Signal Separator block 60 | * 61 | * \param samp_rate Sample rate of input signal 62 | * \param window Firdes window type to scale input samples with 63 | * \param trans_width Transition width for each signal relative to center frequency (w 64 | * = trans_width*center_freq) \param oversampling Oversampling factor (OSF) to ensure 65 | * the whole signal gets passed \param taps_file Determine wether to use a file of 66 | * precalculated taps or caluculate them during runtime \param file_path File path to 67 | * taps file (leave empty if not enabled) 68 | */ 69 | static sptr make(double samp_rate, 70 | int window, 71 | float trans_width, 72 | float oversampling, 73 | bool taps_file, 74 | std::map>& file_path); 75 | 76 | virtual void set_samp_rate(double d_samp_rate) = 0; 77 | 78 | /*! 79 | * Takes integers and does internal cast to firdes::win_type 80 | */ 81 | virtual void set_window(int d_window) = 0; 82 | 83 | virtual void set_trans_width(float d_trans_width) = 0; 84 | virtual void set_oversampling(float d_oversampling) = 0; 85 | }; 86 | 87 | } // namespace inspector 88 | } // namespace gr 89 | 90 | #endif /* INCLUDED_INSPECTOR_SIGNAL_SEPARATOR_C_H */ 91 | -------------------------------------------------------------------------------- /lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012,2016,2018,2019 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Setup library 11 | ######################################################################## 12 | include(GrPlatform) #define LIB_SUFFIX 13 | 14 | ######################################################################## 15 | # QT GUI file generation stuff (Q_OBJECT) 16 | ######################################################################## 17 | include_directories(${Qt5Widgets_INCLUDE_DIRS}) 18 | set(inspector_mod_includedir ${CMAKE_CURRENT_SOURCE_DIR}/../include/gnuradio/inspector) 19 | set(QTGUI_MOC_HEADERS 20 | ${inspector_mod_includedir}/signal_marker.h 21 | ${inspector_mod_includedir}/inspector_form.h 22 | ) 23 | QT5_WRAP_CPP(QTGUI_MOC_OUTFILES ${QTGUI_MOC_HEADERS}) 24 | 25 | list(APPEND inspector_sources 26 | ${QTGUI_MOC_OUTFILES} 27 | signal_separator_c_impl.cc 28 | signal_detector_cvf_impl.cc 29 | signal_extractor_c_impl.cc 30 | qtgui_inspector_sink_vf_impl.cc 31 | inspector_form.cc 32 | signal_marker.cc 33 | ofdm_bouzegzi_c_impl.cc 34 | ofdm_zkf_c_impl.cc 35 | ofdm_synchronizer_cc_impl.cc 36 | ) 37 | 38 | set(inspector_sources "${inspector_sources}" PARENT_SCOPE) 39 | if(NOT inspector_sources) 40 | MESSAGE(STATUS "No C++ sources... skipping lib/") 41 | return() 42 | endif(NOT inspector_sources) 43 | 44 | add_library(gnuradio-inspector SHARED ${inspector_sources}) 45 | target_link_libraries(gnuradio-inspector PUBLIC 46 | gnuradio::gnuradio-runtime 47 | gnuradio::gnuradio-fft 48 | gnuradio::gnuradio-filter 49 | qwt::qwt 50 | Qt5::Widgets 51 | ) 52 | 53 | include(GrPython) 54 | if(ENABLE_PYTHON) 55 | target_compile_definitions(gnuradio-inspector PUBLIC -DENABLE_PYTHON) 56 | # INTERFACE/PRIVATE split so users of the library can choose how to link to Python 57 | # (importantly, extension modules can avoid linking against Python and resolve 58 | # their own Python symbols at runtime through the Python interpreter's linking) 59 | target_link_libraries(gnuradio-inspector INTERFACE Python::Module PRIVATE Python::Python) 60 | endif(ENABLE_PYTHON) 61 | 62 | target_include_directories(gnuradio-inspector 63 | PUBLIC $ 64 | PUBLIC $ 65 | ) 66 | set_target_properties(gnuradio-inspector PROPERTIES DEFINE_SYMBOL "gnuradio_inspector_EXPORTS") 67 | 68 | if(APPLE) 69 | set_target_properties(gnuradio-inspector PROPERTIES 70 | INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" 71 | ) 72 | endif(APPLE) 73 | 74 | ######################################################################## 75 | # Install built library files 76 | ######################################################################## 77 | include(GrMiscUtils) 78 | GR_LIBRARY_FOO(gnuradio-inspector) 79 | 80 | ######################################################################## 81 | # Print summary 82 | ######################################################################## 83 | message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") 84 | message(STATUS "Building for version: ${VERSION} / ${LIBVER}") 85 | 86 | ######################################################################## 87 | # Build and register unit test 88 | ######################################################################## 89 | include(GrTest) 90 | 91 | # If your unit tests require special include paths, add them here 92 | #include_directories() 93 | # List all files that contain Boost.UTF unit tests here 94 | list(APPEND test_inspector_sources 95 | ) 96 | # Anything we need to link to for the unit tests go here 97 | list(APPEND GR_TEST_TARGET_DEPS gnuradio-inspector) 98 | 99 | if(NOT test_inspector_sources) 100 | MESSAGE(STATUS "No C++ unit tests... skipping") 101 | return() 102 | endif(NOT test_inspector_sources) 103 | 104 | foreach(qa_file ${test_inspector_sources}) 105 | GR_ADD_CPP_TEST("inspector_${qa_file}" 106 | ${CMAKE_CURRENT_SOURCE_DIR}/${qa_file} 107 | ) 108 | endforeach(qa_file) 109 | -------------------------------------------------------------------------------- /lib/ofdm_bouzegzi_c_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_OFDM_BOUZEGZI_C_IMPL_H 22 | #define INCLUDED_INSPECTOR_OFDM_BOUZEGZI_C_IMPL_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace gr { 30 | namespace inspector { 31 | 32 | class ofdm_bouzegzi_c_impl : public ofdm_bouzegzi_c 33 | { 34 | public: 35 | static constexpr unsigned int DEFAULT_FFT_LEN = 1024; 36 | static constexpr unsigned int MIN_NOUTPUT_ITEMS = 7000; 37 | static constexpr unsigned int DEFAULT_LEN = 10000; 38 | 39 | private: 40 | int d_Nb; 41 | volk::vector d_x1; 42 | volk::vector d_y1; 43 | volk::vector d_x2; 44 | volk::vector d_y2; 45 | volk::vector d_tmp1; 46 | volk::vector d_tmp2; 47 | volk::vector d_real_pre; 48 | volk::vector d_imag_pre; 49 | volk::vector d_osc_vec; 50 | volk::vector d_sig_shift, d_res; 51 | std::vector d_alpha, d_beta; 52 | std::unique_ptr d_fft; 53 | 54 | void rescale_fft(unsigned int length); 55 | 56 | float autocorr(const gr_complex* sig, int a, int b, int p, unsigned int length); 57 | float cost_func(const gr_complex* sig, int a, int b, unsigned int length); 58 | 59 | public: 60 | ofdm_bouzegzi_c_impl(double samp_rate, 61 | int Nb, 62 | const std::vector& alpha, 63 | const std::vector& beta); 64 | 65 | ~ofdm_bouzegzi_c_impl() override; 66 | 67 | 68 | // Where all the action really happens 69 | int work(int noutput_items, 70 | gr_vector_const_void_star& input_items, 71 | gr_vector_void_star& output_items) override; 72 | }; 73 | 74 | } // namespace inspector 75 | } // namespace gr 76 | 77 | #endif /* INCLUDED_INSPECTOR_OFDM_BOUZEGZI_C_IMPL_H */ 78 | -------------------------------------------------------------------------------- /lib/ofdm_synchronizer_cc_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifdef HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #include "ofdm_synchronizer_cc_impl.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace gr { 32 | namespace inspector { 33 | 34 | ofdm_synchronizer_cc::sptr ofdm_synchronizer_cc::make(int min_items) 35 | { 36 | return gnuradio::get_initial_sptr(new ofdm_synchronizer_cc_impl(min_items)); 37 | } 38 | 39 | 40 | /* 41 | * The private constructor 42 | */ 43 | ofdm_synchronizer_cc_impl::ofdm_synchronizer_cc_impl(int min_items) 44 | : gr::sync_block("ofdm_synchronizer_cc", 45 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 46 | gr::io_signature::make(1, 1, sizeof(gr_complex))) 47 | { 48 | d_fft_len = 0; 49 | d_cp_len = 0; 50 | d_msg_received = false; 51 | d_min_items = min_items; 52 | // message port for parameter estimations 53 | message_port_register_in(pmt::intern("ofdm_in")); 54 | set_msg_handler(pmt::intern("ofdm_in"), 55 | [this](pmt::pmt_t msg) { this->handle_msg(msg); }); 56 | } 57 | 58 | /* 59 | * Our virtual destructor. 60 | */ 61 | ofdm_synchronizer_cc_impl::~ofdm_synchronizer_cc_impl() {} 62 | 63 | void ofdm_synchronizer_cc_impl::handle_msg(pmt::pmt_t msg) 64 | { 65 | // get FFT and CP length out of parameter estmation msg 66 | gr::thread::scoped_lock guard(d_mutex); 67 | auto fftlen = static_cast( 68 | pmt::to_float(pmt::tuple_ref(pmt::tuple_ref(msg, 4), 1))); 69 | auto cplen = static_cast( 70 | pmt::to_float(pmt::tuple_ref(pmt::tuple_ref(msg, 5), 1))); 71 | if (fftlen < 10000 && fftlen > 0 && cplen < 1000 && cplen > 0) { 72 | d_fft_len = fftlen; 73 | d_cp_len = cplen; 74 | d_msg_received = true; 75 | d_tag_pos = std::optional{}; 76 | } 77 | } 78 | 79 | std::vector ofdm_synchronizer_cc_impl::autocorr(const gr_complex* in, int len) 80 | { 81 | std::vector result; 82 | gr_complex* temp = (gr_complex*)volk_malloc((len - d_fft_len) * sizeof(gr_complex), 83 | volk_get_alignment()); 84 | gr_complex Rxx; 85 | 86 | // shift equal to fft length 87 | volk_32fc_x2_multiply_conjugate_32fc(temp, &in[d_fft_len], in, len - d_fft_len); 88 | // sum up over cyclic prefix length 89 | for (unsigned int i = 0; i < len - d_fft_len - d_cp_len; i++) { 90 | Rxx = gr_complex(0, 0); 91 | for (unsigned int k = 0; k < d_cp_len; k++) { 92 | Rxx += temp[i + k]; 93 | } 94 | result.push_back(Rxx); 95 | } 96 | volk_free(temp); 97 | return result; 98 | } 99 | 100 | int ofdm_synchronizer_cc_impl::work(int noutput_items, 101 | gr_vector_const_void_star& input_items, 102 | gr_vector_void_star& output_items) 103 | { 104 | const gr_complex* in = (const gr_complex*)input_items[0]; 105 | gr_complex* out = (gr_complex*)output_items[0]; 106 | if (!d_msg_received) { 107 | return noutput_items; 108 | } 109 | 110 | // skip work function if too freq items provided 111 | if (static_cast(noutput_items) < d_min_items) { 112 | return 0; 113 | } 114 | 115 | std::vector r = autocorr(in, noutput_items); 116 | volk::vector r_mag(noutput_items - d_fft_len - d_cp_len); 117 | volk_32fc_magnitude_32f(r_mag.data(), r.data(), noutput_items - d_fft_len - d_cp_len); 118 | std::vector r_vec(r_mag.begin(), 119 | r_mag.begin() + noutput_items - d_fft_len - d_cp_len); 120 | // calculate argmax 121 | int k = std::distance( 122 | r_vec.begin(), 123 | std::max_element(r_vec.begin(), r_vec.begin() + d_fft_len + d_cp_len)); 124 | float n = std::arg(r[k]); // phase at argmax 125 | // set frequency offset compensation 126 | d_rotator.set_phase_incr(std::exp(gr_complex(0, -n / d_fft_len))); 127 | 128 | // correct frequency 129 | for (int i = 0; i < noutput_items; i++) { 130 | out[i] = d_rotator.rotate(in[i]); 131 | } 132 | if (!d_tag_pos) { 133 | d_tag_pos = k; 134 | } 135 | // add stream tags 136 | while (d_tag_pos < nitems_written(0) + noutput_items) { 137 | add_item_tag(0, 138 | d_tag_pos.value(), 139 | pmt::intern("symbol"), 140 | pmt::from_long(d_fft_len + d_cp_len)); 141 | d_tag_pos.value() += d_fft_len + d_cp_len; 142 | } 143 | 144 | // Tell runtime system how many output items we produced. 145 | return noutput_items; 146 | } 147 | 148 | } /* namespace inspector */ 149 | } /* namespace gr */ 150 | -------------------------------------------------------------------------------- /lib/ofdm_synchronizer_cc_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_OFDM_SYNCHRONIZER_CC_IMPL_H 22 | #define INCLUDED_INSPECTOR_OFDM_SYNCHRONIZER_CC_IMPL_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | class ofdm_synchronizer_cc_impl : public ofdm_synchronizer_cc 31 | { 32 | private: 33 | unsigned int d_fft_len, d_cp_len, d_min_items; 34 | std::optional d_tag_pos; 35 | bool d_msg_received; 36 | blocks::rotator d_rotator; 37 | gr::thread::mutex d_mutex; 38 | 39 | public: 40 | ofdm_synchronizer_cc_impl(int min_items); 41 | ~ofdm_synchronizer_cc_impl(); 42 | 43 | void handle_msg(pmt::pmt_t msg); 44 | std::vector autocorr(const gr_complex* in, int len); 45 | 46 | // Where all the action really happens 47 | int work(int noutput_items, 48 | gr_vector_const_void_star& input_items, 49 | gr_vector_void_star& output_items); 50 | }; 51 | 52 | } // namespace inspector 53 | } // namespace gr 54 | 55 | #endif /* INCLUDED_INSPECTOR_OFDM_SYNCHRONIZER_CC_IMPL_H */ 56 | -------------------------------------------------------------------------------- /lib/ofdm_zkf_c_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_OFDM_ZKF_C_IMPL_H 22 | #define INCLUDED_INSPECTOR_OFDM_ZKF_C_IMPL_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | class ofdm_zkf_c_impl : public ofdm_zkf_c 31 | { 32 | private: 33 | double d_samp_rate; 34 | unsigned int d_signal; 35 | std::vector d_typ_len, d_typ_cp; 36 | fft::fft_complex_fwd* d_fft; 37 | int d_min_items; 38 | 39 | public: 40 | ofdm_zkf_c_impl(double samp_rate, 41 | int signal, 42 | int min_items, 43 | const std::vector& typ_len, 44 | const std::vector& typ_cp); 45 | ~ofdm_zkf_c_impl(); 46 | std::vector autocorr(const gr_complex* in, int len); 47 | gr_complex* tv_autocorr(const gr_complex* in, int len, int shift); 48 | int round_to_list(int val, std::vector* list); 49 | void resize_fft(int size); 50 | 51 | void set_samp_rate(double d_samp_rate); 52 | 53 | pmt::pmt_t pack_message(float subc, float time, int fft, int cp); 54 | 55 | // Where all the action really happens 56 | int work(int noutput_items, 57 | gr_vector_const_void_star& input_items, 58 | gr_vector_void_star& output_items); 59 | }; 60 | 61 | } // namespace inspector 62 | } // namespace gr 63 | 64 | #endif /* INCLUDED_INSPECTOR_OFDM_ZKF_C_IMPL_H */ 65 | -------------------------------------------------------------------------------- /lib/qtgui_inspector_sink_vf_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_QTGUI_INSPECTOR_SINK_VF_IMPL_H 22 | #define INCLUDED_INSPECTOR_QTGUI_INSPECTOR_SINK_VF_IMPL_H 23 | 24 | #include 25 | #include 26 | #include 27 | namespace gr { 28 | namespace inspector { 29 | 30 | class qtgui_inspector_sink_vf_impl : public qtgui_inspector_sink_vf 31 | { 32 | private: 33 | int d_argc, d_rf_unit, d_fft_len; 34 | bool d_manual, d_auto_sent; 35 | float d_cfreq; 36 | double d_samp_rate; 37 | char* d_argv; 38 | QWidget* d_parent; 39 | pmt::pmt_t d_tmp_msg; 40 | inspector_form* d_main_gui; 41 | QApplication* d_qApplication; 42 | std::vector d_buffer; 43 | std::vector> d_rf_map; 44 | gr::msg_queue* d_msg_queue; 45 | 46 | public: 47 | qtgui_inspector_sink_vf_impl(double samp_rate, 48 | int fft_len, 49 | float cfreq, 50 | int rf_unit, 51 | int msgports, 52 | bool manual, 53 | QWidget* parent); 54 | ~qtgui_inspector_sink_vf_impl(); 55 | 56 | QWidget* qwidget(); 57 | 58 | #ifdef ENABLE_PYTHON 59 | PyObject* pyqwidget(); 60 | #else 61 | void* pyqwidget(); 62 | #endif 63 | 64 | 65 | void handle_msg(pmt::pmt_t msg); 66 | void handle_analysis(pmt::pmt_t msg); 67 | void unpack_message(pmt::pmt_t msg); 68 | void send_manual_message(float center, float bw); 69 | void set_rf_unit(int unit); 70 | void set_samp_rate(double d_samp_rate); 71 | 72 | void initialize(); 73 | 74 | // Where all the action really happens 75 | int work(int noutput_items, 76 | gr_vector_const_void_star& input_items, 77 | gr_vector_void_star& output_items); 78 | 79 | 80 | void set_cfreq(float cfreq) 81 | { 82 | d_cfreq = cfreq; 83 | d_main_gui->set_cfreq(cfreq); 84 | d_main_gui->set_axis_x(-d_samp_rate / 2, d_samp_rate / 2 - 1); 85 | } 86 | }; 87 | 88 | } // namespace inspector 89 | } // namespace gr 90 | 91 | #endif /* INCLUDED_INSPECTOR_QTGUI_INSPECTOR_SINK_VF_IMPL_H */ 92 | -------------------------------------------------------------------------------- /lib/signal_detector_cvf_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_SIGNAL_DETECTOR_CVF_IMPL_H 22 | #define INCLUDED_INSPECTOR_SIGNAL_DETECTOR_CVF_IMPL_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | namespace gr { 33 | namespace inspector { 34 | 35 | class signal_detector_cvf_impl : public signal_detector_cvf 36 | { 37 | private: 38 | bool d_auto_threshold; 39 | unsigned int d_fft_len; 40 | unsigned int d_tmpbuflen; 41 | float d_threshold, d_sensitivity, d_average, d_quantization, d_min_bw; 42 | std::vector d_tmpbuf; 43 | std::vector d_pxx; 44 | std::vector d_tmp_pxx; 45 | std::vector d_pxx_out; 46 | double d_samp_rate; 47 | std::ofstream logfile; 48 | 49 | std::vector> d_avg_filter; 50 | fft::window::win_type d_window_type; 51 | std::vector d_window; 52 | std::vector> d_signal_edges; 53 | std::unique_ptr d_fft; 54 | std::vector d_freq; 55 | std::string d_filename; 56 | 57 | void write_logfile_header(); 58 | void write_logfile_entry(); 59 | 60 | public: 61 | signal_detector_cvf_impl(double samp_rate, 62 | int fft_len, 63 | int window_type, 64 | float threshold, 65 | float sensitivity, 66 | bool auto_threshold, 67 | float average, 68 | float quantization, 69 | float min_bw, 70 | const char* filename); 71 | 72 | ~signal_detector_cvf_impl(); 73 | 74 | // set window coefficients 75 | void build_window(); 76 | // create frequency vector 77 | std::vector build_freq(); 78 | // auto threshold calculation 79 | void build_threshold(); 80 | // signal grouping logic 81 | std::vector> find_signal_edges(); 82 | 83 | pmt::pmt_t pack_message(); 84 | // check if signals have changed 85 | bool compare_signal_edges(std::vector>* edges); 86 | // PSD estimation 87 | void periodogram(float* pxx, const gr_complex* signal); 88 | 89 | int work(int noutput_items, 90 | gr_vector_const_void_star& input_items, 91 | gr_vector_void_star& output_items); 92 | 93 | void set_samp_rate(double d_samp_rate) 94 | { 95 | signal_detector_cvf_impl::d_samp_rate = d_samp_rate; 96 | } 97 | 98 | void set_fft_len(int fft_len); 99 | void set_window_type(int d_window); 100 | 101 | void set_threshold(float d_threshold) 102 | { 103 | signal_detector_cvf_impl::d_threshold = d_threshold; 104 | } 105 | 106 | void set_sensitivity(float d_sensitivity) 107 | { 108 | signal_detector_cvf_impl::d_sensitivity = d_sensitivity; 109 | } 110 | 111 | void set_auto_threshold(bool d_auto_threshold) 112 | { 113 | signal_detector_cvf_impl::d_auto_threshold = d_auto_threshold; 114 | } 115 | 116 | void set_average(float d_average) 117 | { 118 | signal_detector_cvf_impl::d_average = d_average; 119 | for (unsigned int i = 0; i < d_fft_len; i++) { 120 | d_avg_filter[i].set_taps(d_average); 121 | } 122 | } 123 | 124 | void set_quantization(float d_quantization) 125 | { 126 | signal_detector_cvf_impl::d_quantization = d_quantization; 127 | } 128 | }; 129 | 130 | } // namespace inspector 131 | } // namespace gr 132 | 133 | #endif /* INCLUDED_INSPECTOR_SIGNAL_DETECTOR_CVF_IMPL_H */ 134 | -------------------------------------------------------------------------------- /lib/signal_extractor_c_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifdef HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #include "signal_extractor_c_impl.h" 26 | #include 27 | #include 28 | #include 29 | 30 | namespace gr { 31 | namespace inspector { 32 | 33 | signal_extractor_c::sptr 34 | signal_extractor_c::make(int signal, bool resample, float rate, float osf) 35 | { 36 | return gnuradio::get_initial_sptr( 37 | new signal_extractor_c_impl(signal, resample, rate, osf)); 38 | } 39 | 40 | 41 | /* 42 | * The private constructor 43 | */ 44 | signal_extractor_c_impl::signal_extractor_c_impl(int signal, 45 | bool resample, 46 | float rate, 47 | float osf) 48 | : gr::sync_block("signal_extractor_c", 49 | gr::io_signature::make(0, 0, 0), 50 | gr::io_signature::make(1, 1, sizeof(gr_complex))) 51 | { 52 | message_port_register_in(pmt::intern("sig_in")); 53 | set_msg_handler(pmt::intern("sig_in"), 54 | [this](pmt::pmt_t msg) { this->handle_msg(msg); }); 55 | 56 | 57 | d_signal = signal; 58 | d_oversampling = osf; 59 | d_ready = false; // tell work to not emit anything until a message arrives 60 | d_out_rate = rate; 61 | d_rate = 1; 62 | d_resample = resample; 63 | std::vector taps = 64 | filter::firdes::low_pass(64, 1000, 1000.0 / 64.0, 100. / 64); 65 | d_resampler = new filter::kernel::pfb_arb_resampler_ccf(d_rate, taps, 64); 66 | } 67 | 68 | /* 69 | * Our virtual destructor. 70 | */ 71 | signal_extractor_c_impl::~signal_extractor_c_impl() { delete d_resampler; } 72 | 73 | void signal_extractor_c_impl::handle_msg(pmt::pmt_t msg) 74 | { 75 | if (d_signal + 1 > pmt::length(msg)) { 76 | GR_LOG_WARN(d_logger, "Specified signal does not exist."); 77 | return; 78 | } else { 79 | pmt::pmt_t pmt_samples = pmt::tuple_ref(pmt::vector_ref(msg, d_signal), 3); 80 | d_length = pmt::length(pmt_samples); 81 | for (int i = 0; i < d_length; i++) { 82 | d_samples.push_back(pmt::c32vector_ref(pmt_samples, i)); 83 | } 84 | d_msg_buffer = &d_samples[0]; 85 | d_ready = true; // buffer filled, ready to emit samples 86 | if (d_resample) { 87 | float bw = pmt::to_float(pmt::tuple_ref(pmt::vector_ref(msg, d_signal), 2)); 88 | d_rate = d_out_rate / (d_oversampling * bw); 89 | d_resampler->set_rate(d_rate); 90 | // GR_LOG_INFO(d_logger, "Actual output sample rate: "+std::to_string( 91 | // bw*d_oversampling*d_resampler->interpolation_rate()/d_resampler->decimation_rate())); 92 | } 93 | } 94 | } 95 | 96 | int signal_extractor_c_impl::work(int noutput_items, 97 | gr_vector_const_void_star& input_items, 98 | gr_vector_void_star& output_items) 99 | { 100 | gr_complex* out = (gr_complex*)output_items[0]; 101 | // if no samples received, skip work 102 | if (d_samples.size() > 0) { 103 | int nout; 104 | unsigned int item_count = noutput_items; 105 | // resampling 106 | if (d_resample) { 107 | item_count *= 1 / d_rate; 108 | if (item_count > d_samples.size()) 109 | item_count = d_samples.size(); 110 | d_resampler->filter(out, &d_samples[0], item_count, nout); 111 | d_samples.clear(); 112 | return d_rate * nout; 113 | } 114 | // copy raw samples into output buffer 115 | else { 116 | if (item_count > d_samples.size()) 117 | item_count = d_samples.size(); 118 | memcpy(out, &d_samples[0], sizeof(gr_complex) * item_count); 119 | d_samples.clear(); 120 | return item_count; 121 | } 122 | } else { 123 | return 0; 124 | } 125 | } 126 | 127 | } /* namespace inspector */ 128 | } /* namespace gr */ 129 | -------------------------------------------------------------------------------- /lib/signal_extractor_c_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_SIGNAL_EXTRACTOR_C_IMPL_H 22 | #define INCLUDED_INSPECTOR_SIGNAL_EXTRACTOR_C_IMPL_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace inspector { 29 | 30 | class signal_extractor_c_impl : public signal_extractor_c 31 | { 32 | private: 33 | int d_signal, d_length; 34 | bool d_ready, d_resample; 35 | float d_out_rate, d_oversampling, d_rate; 36 | std::vector d_samples; 37 | gr_complex* d_msg_buffer; 38 | filter::kernel::pfb_arb_resampler_ccf* d_resampler; 39 | 40 | public: 41 | signal_extractor_c_impl(int signal, bool resample, float rate, float osf); 42 | ~signal_extractor_c_impl(); 43 | 44 | // write samples from message in buffer 45 | void handle_msg(pmt::pmt_t msg); 46 | 47 | // Where all the action really happens 48 | int work(int noutput_items, 49 | gr_vector_const_void_star& input_items, 50 | gr_vector_void_star& output_items); 51 | 52 | // callback 53 | void set_signal(int d_signal) { signal_extractor_c_impl::d_signal = d_signal; } 54 | }; 55 | 56 | } // namespace inspector 57 | } // namespace gr 58 | 59 | #endif /* INCLUDED_INSPECTOR_SIGNAL_EXTRACTOR_C_IMPL_H */ 60 | -------------------------------------------------------------------------------- /lib/signal_marker.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc.. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifdef HAVE_CONFIG_H 22 | #include 23 | #endif 24 | 25 | #include 26 | #include 27 | 28 | namespace gr { 29 | namespace inspector { 30 | 31 | signal_marker::signal_marker(int i, QwtPlot* plot) 32 | { 33 | d_plot = plot; 34 | d_number = i; 35 | d_center = new QwtPlotMarker(); 36 | d_label = new QwtPlotMarker(); 37 | d_zone = new QwtPlotZoneItem(); 38 | } 39 | 40 | signal_marker::~signal_marker() 41 | { 42 | delete d_center; 43 | delete d_label; 44 | delete d_zone; 45 | } 46 | 47 | void signal_marker::set_marker(int i, float center, float bw, int unit) 48 | { 49 | d_number = i; 50 | d_freq = center; 51 | d_bw = bw; 52 | d_unit = unit; 53 | d_center->setLineStyle(QwtPlotMarker::VLine); 54 | QColor c = Qt::white; 55 | c.setAlpha(70); 56 | d_center->setLinePen(c); 57 | d_center->setXValue(center / unit); 58 | 59 | QString unittxt = "Hz"; 60 | switch (unit) { 61 | case 1: 62 | d_unittxt = "Hz"; 63 | break; 64 | case 1000: 65 | d_unittxt = "kHz"; 66 | break; 67 | case 1000000: 68 | d_unittxt = "MHz"; 69 | break; 70 | case 1000000000: 71 | d_unittxt = "GHz"; 72 | break; 73 | default: 74 | d_unittxt = "Hz"; 75 | } 76 | 77 | set_label_text(basic_text()); 78 | 79 | d_zone->setOrientation(Qt::Vertical); 80 | c = Qt::red; 81 | c.setAlpha(100); 82 | d_zone->setPen(c); 83 | c.setAlpha(20); 84 | d_zone->setBrush(c); 85 | d_zone->setInterval((center - bw / 2) / unit, (center + bw / 2) / unit); 86 | d_zone->setXAxis(QwtPlot::xBottom); 87 | 88 | d_label->attach(d_plot); 89 | d_zone->attach(d_plot); 90 | d_center->attach(d_plot); 91 | } 92 | 93 | void signal_marker::set_label_y(qreal yval) { d_label->setYValue(yval); } 94 | 95 | QString signal_marker::basic_text() 96 | { 97 | QString qstring; 98 | qstring.push_back("Signal " + QString::number(d_number + 1)); 99 | qstring.append("\n"); 100 | qstring.append("f = " + QString::number(d_freq / d_unit) + " " + d_unittxt); 101 | qstring.append("\n"); 102 | qstring.append("B = " + QString::number(d_bw / d_unit) + " " + d_unittxt); 103 | return qstring; 104 | } 105 | 106 | void signal_marker::set_label_text(QString qstring) 107 | { 108 | QwtText qwttext; 109 | qwttext.setText(qstring); 110 | qwttext.setColor(Qt::red); 111 | d_label->label(); 112 | d_label->setLabelAlignment(Qt::AlignLeft); 113 | d_label->setLabel(qwttext); 114 | d_label->setXValue((d_freq - d_bw / 2 - 300) / d_unit); 115 | d_label->setYValue(13); 116 | } 117 | 118 | void signal_marker::add_text(std::string text) 119 | { 120 | QString qstring = basic_text(); 121 | qstring.append("\n"); 122 | qstring.append(text.c_str()); 123 | set_label_text(qstring); 124 | } 125 | } /* namespace inspector */ 126 | } /* namespace gr */ 127 | -------------------------------------------------------------------------------- /lib/signal_separator_c_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 Free Software Foundation, Inc. 4 | * 5 | * This 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 | * This software 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 this software; 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 | #ifndef INCLUDED_INSPECTOR_SIGNAL_SEPARATOR_C_IMPL_H 22 | #define INCLUDED_INSPECTOR_SIGNAL_SEPARATOR_C_IMPL_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | namespace gr { 35 | namespace inspector { 36 | 37 | class signal_separator_c_impl : public signal_separator_c 38 | { 39 | private: 40 | bool d_use_file; 41 | int d_buffer_len; 42 | unsigned int d_buffer_stage; 43 | float d_trans_width, d_oversampling; 44 | double d_samp_rate; 45 | gr_complex* d_temp_buffer; 46 | 47 | fft::window::win_type d_window; 48 | 49 | std::vector d_filterbank; 50 | std::vector> d_rf_map; 51 | 52 | std::vector build_taps(double cutoff); 53 | std::vector d_decimations; 54 | std::vector d_ntaps; 55 | std::vector d_rotators; 56 | 57 | std::vector d_history_buffer; 58 | std::vector> d_result_vector; 59 | gr::thread::mutex d_mutex; 60 | 61 | std::map> d_precalc; 62 | std::vector d_taps; 63 | 64 | 65 | public: 66 | signal_separator_c_impl(double samp_rate, 67 | int window, 68 | float trans_width, 69 | float oversampling, 70 | bool taps_file, 71 | std::map>& file_path); 72 | 73 | ~signal_separator_c_impl(); 74 | 75 | // free allocated buffer arrays and FIR filters 76 | void free_allocation(); 77 | // build new filter for signal 78 | void build_filter(unsigned int signal); 79 | // build new filters for all signals 80 | void rebuild_all_filters(); 81 | // apply filter no i to history buffer i 82 | void apply_filter(int i); 83 | // trigger rebuild of filters and unpack message 84 | void handle_msg(pmt::pmt_t msg); 85 | // create pmt from filtered samples 86 | pmt::pmt_t pack_message(); 87 | // create RF map from received message 88 | void unpack_message(pmt::pmt_t msg); 89 | 90 | // Where all the action really happens 91 | void forecast(int noutput_items, gr_vector_int& ninput_items_required); 92 | 93 | int general_work(int noutput_items, 94 | gr_vector_int& ninput_items, 95 | gr_vector_const_void_star& input_items, 96 | gr_vector_void_star& output_items); 97 | 98 | // 99 | 100 | double samp_rate() const { return d_samp_rate; } 101 | 102 | void set_samp_rate(double d_samp_rate) 103 | { 104 | signal_separator_c_impl::d_samp_rate = d_samp_rate; 105 | rebuild_all_filters(); 106 | } 107 | 108 | fft::window::win_type window() const { return d_window; } 109 | 110 | void set_window(int d_window) 111 | { 112 | signal_separator_c_impl::d_window = 113 | static_cast(d_window); 114 | rebuild_all_filters(); 115 | } 116 | 117 | float trans_width() const { return d_trans_width; } 118 | 119 | void set_trans_width(float d_trans_width) 120 | { 121 | signal_separator_c_impl::d_trans_width = d_trans_width; 122 | } 123 | 124 | int oversampling() const { return d_oversampling; } 125 | 126 | void set_oversampling(float d_oversampling) 127 | { 128 | signal_separator_c_impl::d_oversampling = d_oversampling; 129 | rebuild_all_filters(); 130 | } 131 | 132 | // 133 | }; 134 | 135 | } // namespace inspector 136 | } // namespace gr 137 | 138 | #endif /* INCLUDED_INSPECTOR_SIGNAL_SEPARATOR_C_IMPL_H */ 139 | -------------------------------------------------------------------------------- /python/inspector/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | *.pyo 4 | build*/ 5 | examples/grc/*.py 6 | -------------------------------------------------------------------------------- /python/inspector/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-inspector 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Include python install macros 11 | ######################################################################## 12 | include(GrPython) 13 | if(NOT PYTHONINTERP_FOUND) 14 | return() 15 | endif() 16 | 17 | add_subdirectory(bindings) 18 | 19 | ######################################################################## 20 | # Install python sources 21 | ######################################################################## 22 | GR_PYTHON_INSTALL( 23 | FILES 24 | __init__.py 25 | DESTINATION ${GR_PYTHON_DIR}/gnuradio/inspector 26 | ) 27 | 28 | ######################################################################## 29 | # Handle the unit tests 30 | ######################################################################## 31 | include(GrTest) 32 | 33 | set(GR_TEST_TARGET_DEPS gnuradio-inspector) 34 | 35 | # Create a package directory that tests can import. It includes everything 36 | # from `python/`. 37 | add_custom_target( 38 | copy_module_for_tests ALL 39 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} 40 | ${CMAKE_BINARY_DIR}/test_modules/gnuradio/inspector/ 41 | ) 42 | 43 | GR_ADD_TEST(qa_ofdm_synchronizer_cc ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_synchronizer_cc.py) 44 | GR_ADD_TEST(qa_ofdm_zkf_c ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ofdm_zkf_c.py) 45 | GR_ADD_TEST(qa_signal_detector_cvf ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_signal_detector_cvf.py) 46 | GR_ADD_TEST(qa_signal_separator_c ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_signal_separator_c.py) -------------------------------------------------------------------------------- /python/inspector/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008,2009 Free Software Foundation, Inc. 3 | # 4 | # SPDX-License-Identifier: GPL-3.0-or-later 5 | # 6 | 7 | # The presence of this file turns this directory into a Python package 8 | 9 | ''' 10 | This is the GNU Radio INSPECTOR module. Place your Python package 11 | description here (python/__init__.py). 12 | ''' 13 | import os 14 | 15 | # import pybind11 generated symbols into the inspector namespace 16 | try: 17 | # this might fail if the module is python-only 18 | from .inspector_python import * 19 | except ModuleNotFoundError: 20 | pass 21 | 22 | # import any pure python here 23 | # 24 | -------------------------------------------------------------------------------- /python/inspector/bindings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # SPDX-License-Identifier: GPL-3.0-or-later 6 | # 7 | 8 | ######################################################################## 9 | # Check if there is C++ code at all 10 | ######################################################################## 11 | if(NOT inspector_sources) 12 | MESSAGE(STATUS "No C++ sources... skipping python bindings") 13 | return() 14 | endif(NOT inspector_sources) 15 | 16 | ######################################################################## 17 | # Check for pygccxml 18 | ######################################################################## 19 | GR_PYTHON_CHECK_MODULE_RAW( 20 | "pygccxml" 21 | "import pygccxml" 22 | PYGCCXML_FOUND 23 | ) 24 | 25 | include(GrPybind) 26 | 27 | ######################################################################## 28 | # Python Bindings 29 | ######################################################################## 30 | 31 | list(APPEND inspector_python_files 32 | ofdm_bouzegzi_c_python.cc 33 | ofdm_synchronizer_cc_python.cc 34 | ofdm_zkf_c_python.cc 35 | qtgui_inspector_sink_vf_python.cc 36 | signal_detector_cvf_python.cc 37 | signal_extractor_c_python.cc 38 | signal_separator_c_python.cc 39 | python_bindings.cc) 40 | 41 | GR_PYBIND_MAKE_OOT(inspector 42 | ../../.. 43 | gr::inspector 44 | "${inspector_python_files}") 45 | 46 | # copy bindings extension for use in QA test module 47 | add_custom_command(TARGET inspector_python POST_BUILD 48 | COMMAND ${CMAKE_COMMAND} -E copy $ 49 | ${CMAKE_BINARY_DIR}/test_modules/gnuradio/inspector/ 50 | ) 51 | 52 | install(TARGETS inspector_python DESTINATION ${GR_PYTHON_DIR}/gnuradio/inspector COMPONENT pythonapi) 53 | -------------------------------------------------------------------------------- /python/inspector/bindings/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnuradio/gr-inspector/ad6a69e84eb847f30fe79ba657ba95ddcb211c0c/python/inspector/bindings/README.md -------------------------------------------------------------------------------- /python/inspector/bindings/bind_oot_file.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import argparse 3 | from gnuradio.bindtool import BindingGenerator 4 | import sys 5 | import tempfile 6 | 7 | parser = argparse.ArgumentParser(description='Bind a GR Out of Tree Block') 8 | parser.add_argument('--module', type=str, 9 | help='Name of gr module containing file to bind (e.g. fft digital analog)') 10 | 11 | parser.add_argument('--output_dir', default=tempfile.gettempdir(), 12 | help='Output directory of generated bindings') 13 | parser.add_argument('--prefix', help='Prefix of Installed GNU Radio') 14 | 15 | parser.add_argument( 16 | '--filename', help="File to be parsed") 17 | 18 | parser.add_argument( 19 | '--defines', help='Set additional defines for precompiler', default=(), nargs='*') 20 | parser.add_argument( 21 | '--include', help='Additional Include Dirs, separated', default=(), nargs='*') 22 | 23 | parser.add_argument( 24 | '--status', help='Location of output file for general status (used during cmake)', default=None 25 | ) 26 | parser.add_argument( 27 | '--flag_automatic', default='0' 28 | ) 29 | parser.add_argument( 30 | '--flag_pygccxml', default='0' 31 | ) 32 | 33 | args = parser.parse_args() 34 | 35 | prefix = args.prefix 36 | output_dir = args.output_dir 37 | defines = tuple(','.join(args.defines).split(',')) 38 | includes = ','.join(args.include) 39 | name = args.module 40 | 41 | namespace = ['gr', name] 42 | prefix_include_root = name 43 | 44 | 45 | with warnings.catch_warnings(): 46 | warnings.filterwarnings("ignore", category=DeprecationWarning) 47 | 48 | bg = BindingGenerator(prefix, namespace, 49 | prefix_include_root, output_dir, define_symbols=defines, addl_includes=includes, 50 | catch_exceptions=False, write_json_output=False, status_output=args.status, 51 | flag_automatic=True if args.flag_automatic.lower() in [ 52 | '1', 'true'] else False, 53 | flag_pygccxml=True if args.flag_pygccxml.lower() in ['1', 'true'] else False) 54 | bg.gen_file_binding(args.filename) 55 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/README.md: -------------------------------------------------------------------------------- 1 | This directory stores templates for docstrings that are scraped from the include header files for each block 2 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/ofdm_bouzegzi_c_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_ofdm_bouzegzi_c = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_ofdm_bouzegzi_c_ofdm_bouzegzi_c = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_ofdm_bouzegzi_c_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/ofdm_synchronizer_cc_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_ofdm_synchronizer_cc = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_ofdm_synchronizer_cc_ofdm_synchronizer_cc = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_ofdm_synchronizer_cc_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/ofdm_zkf_c_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_ofdm_zkf_c = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_ofdm_zkf_c_ofdm_zkf_c_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_ofdm_zkf_c_ofdm_zkf_c_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_inspector_ofdm_zkf_c_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_inspector_ofdm_zkf_c_set_samp_rate = R"doc()doc"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/qtgui_inspector_sink_vf_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_qtgui_inspector_sink_vf_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_qtgui_inspector_sink_vf_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_set_rf_unit = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_set_samp_rate = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_set_cfreq = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_inspector_qtgui_inspector_sink_vf_pyqwidget = R"doc()doc"; 41 | 42 | 43 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/signal_detector_cvf_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_signal_detector_cvf = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_signal_detector_cvf_signal_detector_cvf_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_signal_detector_cvf_signal_detector_cvf_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_inspector_signal_detector_cvf_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_inspector_signal_detector_cvf_set_samp_rate = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_inspector_signal_detector_cvf_set_fft_len = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_inspector_signal_detector_cvf_set_window_type = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_inspector_signal_detector_cvf_set_threshold = R"doc()doc"; 41 | 42 | 43 | static const char *__doc_gr_inspector_signal_detector_cvf_set_sensitivity = R"doc()doc"; 44 | 45 | 46 | static const char *__doc_gr_inspector_signal_detector_cvf_set_auto_threshold = R"doc()doc"; 47 | 48 | 49 | static const char *__doc_gr_inspector_signal_detector_cvf_set_average = R"doc()doc"; 50 | 51 | 52 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/signal_extractor_c_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_signal_extractor_c = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_signal_extractor_c_signal_extractor_c_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_signal_extractor_c_signal_extractor_c_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_inspector_signal_extractor_c_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_inspector_signal_extractor_c_set_signal = R"doc()doc"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /python/inspector/bindings/docstrings/signal_separator_c_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,inspector, __VA_ARGS__ ) 11 | /* 12 | This file contains placeholders for docstrings for the Python bindings. 13 | Do not edit! These were automatically extracted during the binding process 14 | and will be overwritten during the build process 15 | */ 16 | 17 | 18 | 19 | static const char *__doc_gr_inspector_signal_separator_c = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_inspector_signal_separator_c_signal_separator_c_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_inspector_signal_separator_c_signal_separator_c_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_inspector_signal_separator_c_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_inspector_signal_separator_c_set_samp_rate = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_inspector_signal_separator_c_set_window = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_inspector_signal_separator_c_set_trans_width = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_inspector_signal_separator_c_set_oversampling = R"doc()doc"; 41 | 42 | 43 | -------------------------------------------------------------------------------- /python/inspector/bindings/header_utils.py: -------------------------------------------------------------------------------- 1 | # Utilities for reading values in header files 2 | 3 | from argparse import ArgumentParser 4 | import re 5 | 6 | 7 | class PybindHeaderParser: 8 | def __init__(self, pathname): 9 | with open(pathname, 'r') as f: 10 | self.file_txt = f.read() 11 | 12 | def get_flag_automatic(self): 13 | # p = re.compile(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)') 14 | # m = p.search(self.file_txt) 15 | m = re.search(r'BINDTOOL_GEN_AUTOMATIC\(([^\s])\)', self.file_txt) 16 | if (m and m.group(1) == '1'): 17 | return True 18 | else: 19 | return False 20 | 21 | def get_flag_pygccxml(self): 22 | # p = re.compile(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)') 23 | # m = p.search(self.file_txt) 24 | m = re.search(r'BINDTOOL_USE_PYGCCXML\(([^\s])\)', self.file_txt) 25 | if (m and m.group(1) == '1'): 26 | return True 27 | else: 28 | return False 29 | 30 | def get_header_filename(self): 31 | # p = re.compile(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)') 32 | # m = p.search(self.file_txt) 33 | m = re.search(r'BINDTOOL_HEADER_FILE\(([^\s]*)\)', self.file_txt) 34 | if (m): 35 | return m.group(1) 36 | else: 37 | return None 38 | 39 | def get_header_file_hash(self): 40 | # p = re.compile(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)') 41 | # m = p.search(self.file_txt) 42 | m = re.search(r'BINDTOOL_HEADER_FILE_HASH\(([^\s]*)\)', self.file_txt) 43 | if (m): 44 | return m.group(1) 45 | else: 46 | return None 47 | 48 | def get_flags(self): 49 | return f'{self.get_flag_automatic()};{self.get_flag_pygccxml()};{self.get_header_filename()};{self.get_header_file_hash()};' 50 | 51 | 52 | def argParse(): 53 | """Parses commandline args.""" 54 | desc = 'Reads the parameters from the comment block in the pybind files' 55 | parser = ArgumentParser(description=desc) 56 | 57 | parser.add_argument("function", help="Operation to perform on comment block of pybind file", choices=[ 58 | "flag_auto", "flag_pygccxml", "header_filename", "header_file_hash", "all"]) 59 | parser.add_argument( 60 | "pathname", help="Pathname of pybind c++ file to read, e.g. blockname_python.cc") 61 | 62 | return parser.parse_args() 63 | 64 | 65 | if __name__ == "__main__": 66 | # Parse command line options and set up doxyxml. 67 | args = argParse() 68 | 69 | pbhp = PybindHeaderParser(args.pathname) 70 | 71 | if args.function == "flag_auto": 72 | print(pbhp.get_flag_automatic()) 73 | elif args.function == "flag_pygccxml": 74 | print(pbhp.get_flag_pygccxml()) 75 | elif args.function == "header_filename": 76 | print(pbhp.get_header_filename()) 77 | elif args.function == "header_file_hash": 78 | print(pbhp.get_header_file_hash()) 79 | elif args.function == "all": 80 | print(pbhp.get_flags()) 81 | -------------------------------------------------------------------------------- /python/inspector/bindings/ofdm_bouzegzi_c_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(ofdm_bouzegzi_c.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(facb676dd012e68cd2b28cd0b5d57468) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_ofdm_bouzegzi_c(py::module& m) 31 | { 32 | 33 | using ofdm_bouzegzi_c = ::gr::inspector::ofdm_bouzegzi_c; 34 | 35 | 36 | py::class_>(m, "ofdm_bouzegzi_c", D(ofdm_bouzegzi_c)) 38 | 39 | .def(py::init(&ofdm_bouzegzi_c::make), 40 | py::arg("samp_rate"), 41 | py::arg("Nb"), 42 | py::arg("alpha"), 43 | py::arg("beta"), 44 | D(ofdm_bouzegzi_c,make) 45 | ) 46 | 47 | 48 | 49 | 50 | ; 51 | 52 | 53 | 54 | 55 | } 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /python/inspector/bindings/ofdm_synchronizer_cc_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(ofdm_synchronizer_cc.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(b7db46b2a5b6e60d5006115cbbffd512) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_ofdm_synchronizer_cc(py::module& m) 31 | { 32 | 33 | using ofdm_synchronizer_cc = ::gr::inspector::ofdm_synchronizer_cc; 34 | 35 | 36 | py::class_>(m, "ofdm_synchronizer_cc", D(ofdm_synchronizer_cc)) 38 | 39 | .def(py::init(&ofdm_synchronizer_cc::make), 40 | py::arg("min_items"), 41 | D(ofdm_synchronizer_cc,make) 42 | ) 43 | 44 | 45 | 46 | 47 | ; 48 | 49 | 50 | 51 | 52 | } 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /python/inspector/bindings/ofdm_zkf_c_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(ofdm_zkf_c.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(0b8212bf272cca3b8fa21cf118cc7953) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_ofdm_zkf_c(py::module& m) 31 | { 32 | 33 | using ofdm_zkf_c = ::gr::inspector::ofdm_zkf_c; 34 | 35 | 36 | py::class_>(m, "ofdm_zkf_c", D(ofdm_zkf_c)) 38 | 39 | .def(py::init(&ofdm_zkf_c::make), 40 | py::arg("samp_rate"), 41 | py::arg("signal"), 42 | py::arg("min_items"), 43 | py::arg("typ_len"), 44 | py::arg("typ_cp"), 45 | D(ofdm_zkf_c,make) 46 | ) 47 | 48 | 49 | 50 | 51 | 52 | 53 | .def("set_samp_rate",&ofdm_zkf_c::set_samp_rate, 54 | py::arg("d_samp_rate"), 55 | D(ofdm_zkf_c,set_samp_rate) 56 | ) 57 | 58 | ; 59 | 60 | 61 | 62 | 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /python/inspector/bindings/python_bindings.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 13 | #include 14 | #include 15 | #include 16 | namespace py = pybind11; 17 | 18 | // Headers for binding functions 19 | /**************************************/ 20 | // The following comment block is used for 21 | // gr_modtool to insert function prototypes 22 | // Please do not delete 23 | /**************************************/ 24 | // BINDING_FUNCTION_PROTOTYPES( 25 | void bind_ofdm_bouzegzi_c(py::module& m); 26 | void bind_ofdm_synchronizer_cc(py::module& m); 27 | void bind_ofdm_zkf_c(py::module& m); 28 | void bind_qtgui_inspector_sink_vf(py::module& m); 29 | void bind_signal_detector_cvf(py::module& m); 30 | void bind_signal_extractor_c(py::module& m); 31 | void bind_signal_separator_c(py::module& m); 32 | // ) END BINDING_FUNCTION_PROTOTYPES 33 | 34 | 35 | // We need this hack because import_array() returns NULL 36 | // for newer Python versions. 37 | // This function is also necessary because it ensures access to the C API 38 | // and removes a warning. 39 | void* init_numpy() 40 | { 41 | import_array(); 42 | return NULL; 43 | } 44 | namespace std { 45 | struct map_float_vector{ 46 | map_float_vector(std::map> &vect) : vect(vect){} 47 | std::map> vect; 48 | }; 49 | } 50 | 51 | PYBIND11_MODULE(inspector_python, m) 52 | { 53 | // Initialize the numpy C API 54 | // (otherwise we will see segmentation faults) 55 | init_numpy(); 56 | 57 | // Allow access to base block methods 58 | py::module::import("gnuradio.gr"); 59 | py::module::import("gnuradio.qtgui.qtgui_python"); 60 | 61 | 62 | /**************************************/ 63 | // The following comment block is used for 64 | // gr_modtool to insert binding function calls 65 | // Please do not delete 66 | /**************************************/ 67 | // BINDING_FUNCTION_CALLS( 68 | bind_ofdm_bouzegzi_c(m); 69 | bind_ofdm_synchronizer_cc(m); 70 | bind_ofdm_zkf_c(m); 71 | bind_qtgui_inspector_sink_vf(m); 72 | bind_signal_detector_cvf(m); 73 | bind_signal_extractor_c(m); 74 | bind_signal_separator_c(m); 75 | 76 | py::class_(m, "map_float_vector") 77 | .def(py::init>&>()); 78 | // ) END BINDING_FUNCTION_CALLS 79 | } 80 | -------------------------------------------------------------------------------- /python/inspector/bindings/qtgui_inspector_sink_vf_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(qtgui_inspector_sink_vf.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(3cba9d5762aa8be373642afe7c83fb6c) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | #include 30 | void bind_qtgui_inspector_sink_vf(py::module& m) 31 | { 32 | 33 | using qtgui_inspector_sink_vf = ::gr::inspector::qtgui_inspector_sink_vf; 34 | 35 | 36 | py::class_>(m, "qtgui_inspector_sink_vf", D(qtgui_inspector_sink_vf)) 38 | 39 | .def(py::init(&qtgui_inspector_sink_vf::make), 40 | py::arg("samp_rate"), 41 | py::arg("fft_len"), 42 | py::arg("cfreq") = 0, 43 | py::arg("rf_unit") = 1000000, 44 | py::arg("msgports") = 1, 45 | py::arg("manual") = false, 46 | py::arg("parent") = nullptr, 47 | D(qtgui_inspector_sink_vf,make) 48 | ) 49 | 50 | 51 | 52 | 53 | 54 | 55 | .def("set_rf_unit",&qtgui_inspector_sink_vf::set_rf_unit, 56 | py::arg("unit"), 57 | D(qtgui_inspector_sink_vf,set_rf_unit) 58 | ) 59 | 60 | 61 | 62 | .def("set_samp_rate",&qtgui_inspector_sink_vf::set_samp_rate, 63 | py::arg("d_samp_rate"), 64 | D(qtgui_inspector_sink_vf,set_samp_rate) 65 | ) 66 | 67 | 68 | 69 | .def("set_cfreq",&qtgui_inspector_sink_vf::set_cfreq, 70 | py::arg("cfreq"), 71 | D(qtgui_inspector_sink_vf,set_cfreq) 72 | ) 73 | 74 | 75 | 76 | .def("pyqwidget",[](std::shared_ptr p) { 77 | return PyLong_AsLongLong((PyObject*)p->pyqwidget()); 78 | }, 79 | D(qtgui_inspector_sink_vf,pyqwidget) 80 | ) 81 | 82 | ; 83 | 84 | 85 | 86 | 87 | } 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /python/inspector/bindings/signal_detector_cvf_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(signal_detector_cvf.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(58cc2d96d45fd2c15debf81fc2af08a1) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_signal_detector_cvf(py::module& m) 31 | { 32 | 33 | using signal_detector_cvf = ::gr::inspector::signal_detector_cvf; 34 | 35 | 36 | py::class_>(m, "signal_detector_cvf", D(signal_detector_cvf)) 38 | 39 | .def(py::init(&signal_detector_cvf::make), 40 | py::arg("samp_rate"), 41 | py::arg("fft_len") = 1024, 42 | py::arg("window_type") = 0, 43 | py::arg("threshold") = 0.69999999999999996, 44 | py::arg("sensitivity") = 0.20000000000000001, 45 | py::arg("auto_threshold") = true, 46 | py::arg("average") = 0.80000000000000004, 47 | py::arg("quantization") = 0.01, 48 | py::arg("min_bw") = 0., 49 | py::arg("filename") = "", 50 | D(signal_detector_cvf,make) 51 | ) 52 | 53 | 54 | 55 | 56 | 57 | 58 | .def("set_samp_rate",&signal_detector_cvf::set_samp_rate, 59 | py::arg("d_samp_rate"), 60 | D(signal_detector_cvf,set_samp_rate) 61 | ) 62 | 63 | 64 | 65 | .def("set_fft_len",&signal_detector_cvf::set_fft_len, 66 | py::arg("fft_len"), 67 | D(signal_detector_cvf,set_fft_len) 68 | ) 69 | 70 | 71 | 72 | .def("set_window_type",&signal_detector_cvf::set_window_type, 73 | py::arg("d_window"), 74 | D(signal_detector_cvf,set_window_type) 75 | ) 76 | 77 | 78 | 79 | .def("set_threshold",&signal_detector_cvf::set_threshold, 80 | py::arg("d_threshold"), 81 | D(signal_detector_cvf,set_threshold) 82 | ) 83 | 84 | 85 | 86 | .def("set_sensitivity",&signal_detector_cvf::set_sensitivity, 87 | py::arg("d_sensitivity"), 88 | D(signal_detector_cvf,set_sensitivity) 89 | ) 90 | 91 | 92 | 93 | .def("set_auto_threshold",&signal_detector_cvf::set_auto_threshold, 94 | py::arg("d_auto_threshold"), 95 | D(signal_detector_cvf,set_auto_threshold) 96 | ) 97 | 98 | 99 | 100 | .def("set_average",&signal_detector_cvf::set_average, 101 | py::arg("d_average"), 102 | D(signal_detector_cvf,set_average) 103 | ) 104 | 105 | ; 106 | 107 | 108 | 109 | 110 | } 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /python/inspector/bindings/signal_extractor_c_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(signal_extractor_c.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(f687c7b07ffe9188897e1ac19ed40cda) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_signal_extractor_c(py::module& m) 31 | { 32 | 33 | using signal_extractor_c = ::gr::inspector::signal_extractor_c; 34 | 35 | 36 | py::class_>(m, "signal_extractor_c", D(signal_extractor_c)) 38 | 39 | .def(py::init(&signal_extractor_c::make), 40 | py::arg("signal"), 41 | py::arg("resample") = false, 42 | py::arg("rate") = 1., 43 | py::arg("osf") = 1., 44 | D(signal_extractor_c,make) 45 | ) 46 | 47 | 48 | 49 | 50 | 51 | 52 | .def("set_signal",&signal_extractor_c::set_signal, 53 | py::arg("signal"), 54 | D(signal_extractor_c,set_signal) 55 | ) 56 | 57 | ; 58 | 59 | 60 | 61 | 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /python/inspector/bindings/signal_separator_c_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(signal_separator_c.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(730bc5a1d9d718ce4f7e3380ea16614c) */ 18 | /***********************************************************************************/ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace py = pybind11; 25 | 26 | #include 27 | // pydoc.h is automatically generated in the build directory 28 | #include 29 | 30 | void bind_signal_separator_c(py::module& m) 31 | { 32 | 33 | using signal_separator_c = ::gr::inspector::signal_separator_c; 34 | 35 | 36 | py::class_>(m, "signal_separator_c", D(signal_separator_c)) 38 | 39 | .def(py::init(&signal_separator_c::make), 40 | py::arg("samp_rate"), 41 | py::arg("window"), 42 | py::arg("trans_width"), 43 | py::arg("oversampling"), 44 | py::arg("taps_file"), 45 | py::arg("file_path"), 46 | D(signal_separator_c,make) 47 | ) 48 | 49 | 50 | 51 | 52 | 53 | 54 | .def("set_samp_rate",&signal_separator_c::set_samp_rate, 55 | py::arg("d_samp_rate"), 56 | D(signal_separator_c,set_samp_rate) 57 | ) 58 | 59 | 60 | 61 | .def("set_window",&signal_separator_c::set_window, 62 | py::arg("d_window"), 63 | D(signal_separator_c,set_window) 64 | ) 65 | 66 | 67 | 68 | .def("set_trans_width",&signal_separator_c::set_trans_width, 69 | py::arg("d_trans_width"), 70 | D(signal_separator_c,set_trans_width) 71 | ) 72 | 73 | 74 | 75 | .def("set_oversampling",&signal_separator_c::set_oversampling, 76 | py::arg("d_oversampling"), 77 | D(signal_separator_c,set_oversampling) 78 | ) 79 | 80 | ; 81 | 82 | 83 | 84 | 85 | } 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /python/inspector/qa_ofdm_synchronizer_cc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2019 Free Software Foundation, Inc.. 5 | # 6 | # This 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 | # This software 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 software; 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 | from gnuradio import gr, gr_unittest 23 | from gnuradio import blocks, analog 24 | try: 25 | from gnuradio import inspector 26 | except ImportError: 27 | import os 28 | import sys 29 | dirname, filename = os.path.split(os.path.abspath(__file__)) 30 | sys.path.append(os.path.join(dirname, "bindings")) 31 | from gnuradio import inspector 32 | import numpy as np 33 | import time 34 | import pmt 35 | 36 | 37 | class qa_ofdm_synchronizer_cc(gr_unittest.TestCase): 38 | 39 | def setUp(self): 40 | self.tb = gr.top_block() 41 | 42 | def tearDown(self): 43 | self.tb = None 44 | 45 | def test_001_t(self): 46 | # set up fg 47 | fft_len = 256 48 | cp_len = 32 49 | samp_rate = 32000 50 | data = np.random.choice([-1, 1], [100, fft_len]) 51 | 52 | timefreq = np.fft.ifft(data, axis=0) 53 | 54 | # add cp 55 | timefreq = np.hstack((timefreq[:, -cp_len:], timefreq)) 56 | 57 | # msg (only 4th and 5th tuples are needed) 58 | id1 = pmt.make_tuple(pmt.intern("Signal"), pmt.from_uint64(0)) 59 | name = pmt.make_tuple(pmt.intern("OFDM"), pmt.from_float(1.0)) 60 | id2 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(0.0)) 61 | id3 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(0.0)) 62 | id4 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(256)) 63 | id5 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(32)) 64 | msg = pmt.make_tuple(id1, name, id2, id3, id4, id5) 65 | 66 | tx = np.reshape(timefreq, (1, -1)) 67 | 68 | # GR time! 69 | src = blocks.vector_source_c(tx[0].tolist(), True, 1, []) 70 | freq_offset = analog.sig_source_c(1, analog.GR_SIN_WAVE, 71 | 50.0 / samp_rate, 1.0, 0.0) 72 | mixer = blocks.multiply_cc() 73 | sync = inspector.ofdm_synchronizer_cc(4096) 74 | dst = blocks.vector_sink_c() 75 | dst2 = blocks.vector_sink_c() 76 | msg_src = blocks.message_strobe(msg, 0) 77 | 78 | # connect 79 | self.tb.connect(src, (mixer, 0)) 80 | self.tb.connect(freq_offset, (mixer, 1)) 81 | self.tb.connect(mixer, sync) 82 | self.tb.msg_connect((msg_src, 'strobe'), (sync, 'ofdm_in')) 83 | self.tb.connect(sync, dst) 84 | self.tb.connect(src, dst2) 85 | 86 | self.tb.start() 87 | time.sleep(0.1) 88 | self.tb.stop() 89 | self.tb.wait() 90 | 91 | # check data 92 | output = dst.data() 93 | expect = dst2.data() 94 | 95 | # block outputs 0j until it has enough OFDM symbols to perform estimations 96 | k = next((k for k in range(len(output)) if output[k] != 0j)) 97 | 98 | # use 10,000 samples for comparison since block fails sometimes 99 | # for one work function 100 | output = output[k:k + 10000] 101 | expect = expect[k:k + 10000] 102 | 103 | self.assertComplexTuplesAlmostEqual2( 104 | expect, output, abs_eps=0.001, rel_eps=10) 105 | 106 | 107 | if __name__ == '__main__': 108 | gr_unittest.run(qa_ofdm_synchronizer_cc) 109 | -------------------------------------------------------------------------------- /python/inspector/qa_ofdm_zkf_c.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2019 Free Software Foundation, Inc.. 5 | # 6 | # This 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 | # This software 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 software; 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 | from gnuradio import gr, gr_unittest 23 | from gnuradio import blocks 24 | try: 25 | from gnuradio import inspector 26 | except ImportError: 27 | import os 28 | import sys 29 | dirname, filename = os.path.split(os.path.abspath(__file__)) 30 | sys.path.append(os.path.join(dirname, "bindings")) 31 | from gnuradio import inspector 32 | import numpy as np 33 | import time 34 | import pmt 35 | 36 | 37 | class qa_ofdm_zkf_c(gr_unittest.TestCase): 38 | 39 | def setUp(self): 40 | self.tb = gr.top_block() 41 | 42 | def tearDown(self): 43 | self.tb = None 44 | 45 | def test_001_t(self): 46 | # set up fg 47 | fft_len = 256 48 | cp_len = 32 49 | samp_rate = 32000 50 | data = np.random.choice([-1, 1], [100, fft_len]) 51 | 52 | timefreq = np.fft.ifft(data, axis=0) 53 | 54 | # add cp 55 | timefreq = np.hstack((timefreq[:, -cp_len:], timefreq)) 56 | 57 | tx = np.reshape(timefreq, (1, -1)) 58 | 59 | # GR time! 60 | src = blocks.vector_source_c(tx[0].tolist(), True, 1, []) 61 | analyzer = inspector.ofdm_zkf_c(samp_rate, 0, 7000, [128, 256, 512, 1024], [8, 16, 32, 64]) 62 | snk = blocks.message_debug() 63 | 64 | # connect 65 | self.tb.connect(src, analyzer) 66 | self.tb.msg_connect((analyzer, 'ofdm_out'), (snk, 'store')) 67 | 68 | self.tb.start() 69 | time.sleep(1.0) 70 | self.tb.stop() 71 | self.tb.wait() 72 | 73 | # check data 74 | result = snk.get_message(0) 75 | 76 | fft_result = pmt.to_float(pmt.tuple_ref(pmt.tuple_ref(result, 4), 1)) 77 | cp_result = pmt.to_float(pmt.tuple_ref(pmt.tuple_ref(result, 5), 1)) 78 | 79 | self.assertAlmostEqual(fft_len, fft_result) 80 | self.assertAlmostEqual(cp_len, cp_result) 81 | 82 | 83 | if __name__ == '__main__': 84 | gr_unittest.run(qa_ofdm_zkf_c) 85 | -------------------------------------------------------------------------------- /python/inspector/qa_signal_detector_cvf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2019 Free Software Foundation Inc.. 5 | # 6 | # This 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 | # This software 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 software; 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 | from gnuradio import gr, gr_unittest 22 | from gnuradio import blocks, analog 23 | from gnuradio.fft import window 24 | import time 25 | import numpy 26 | import pmt 27 | try: 28 | from gnuradio import inspector 29 | except ImportError: 30 | import os 31 | import sys 32 | dirname, filename = os.path.split(os.path.abspath(__file__)) 33 | sys.path.append(os.path.join(dirname, "bindings")) 34 | from gnuradio import inspector 35 | 36 | 37 | class qa_signal_detector_cvf (gr_unittest.TestCase): 38 | 39 | def setUp(self): 40 | self.tb = gr.top_block() 41 | 42 | def tearDown(self): 43 | self.tb = None 44 | 45 | def test_001_t(self): 46 | src1 = analog.sig_source_c(32000, analog.GR_COS_WAVE, 47 | 12500, 3) 48 | 49 | src2 = analog.sig_source_c(32000, analog.GR_COS_WAVE, 50 | 9800, 3) 51 | 52 | add = blocks.add_cc() 53 | detector = inspector.signal_detector_cvf(32000, 4096, 54 | window.WIN_BLACKMAN_hARRIS, 55 | -80, 0.6, False, 0.5, 0.001) 56 | dst1 = blocks.null_sink(gr.sizeof_float * 4096) 57 | msg_dst = blocks.message_debug() 58 | 59 | # connections 60 | self.tb.connect(src1, (add, 0)) 61 | self.tb.connect(src2, (add, 1)) 62 | self.tb.connect(add, detector) 63 | self.tb.connect((detector, 0), dst1) 64 | self.tb.msg_connect((detector, 'map_out'), (msg_dst, 'store')) 65 | self.tb.start() 66 | time.sleep(0.5) 67 | self.tb.stop() 68 | self.tb.wait() 69 | 70 | # take most recent message 71 | msg = msg_dst.get_message(msg_dst.num_messages() - 1) 72 | res_vector = numpy.empty([0, 2]) 73 | for i in range(pmt.length(msg)): 74 | row = pmt.vector_ref(msg, i) 75 | res_vector = numpy.vstack((res_vector, numpy.array( 76 | [pmt.f32vector_ref(row, 0), pmt.f32vector_ref(row, 1)] 77 | ))) 78 | 79 | self.assertAlmostEqual(9800.0, res_vector[0][0], delta=50) 80 | self.assertAlmostEqual(0.0, res_vector[0][1], delta=100) 81 | self.assertAlmostEqual(12500.0, res_vector[1][0], delta=50) 82 | self.assertAlmostEqual(0.0, res_vector[1][1], delta=100) 83 | 84 | 85 | if __name__ == '__main__': 86 | gr_unittest.run(qa_signal_detector_cvf) 87 | -------------------------------------------------------------------------------- /python/inspector/qa_signal_separator_c.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2019 Free Software Foundation, Inc. 5 | # 6 | # This 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 | # This software 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 software; 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 | from gnuradio import gr, gr_unittest 23 | from gnuradio import blocks, filter 24 | from gnuradio.fft import window 25 | try: 26 | from gnuradio import inspector 27 | except ImportError: 28 | import os 29 | import sys 30 | dirname, filename = os.path.split(os.path.abspath(__file__)) 31 | sys.path.append(os.path.join(dirname, "bindings")) 32 | from gnuradio import inspector 33 | import pmt 34 | import numpy 35 | import time 36 | 37 | 38 | class qa_signal_separator_c (gr_unittest.TestCase): 39 | 40 | def setUp(self): 41 | self.tb = gr.top_block() 42 | 43 | def tearDown(self): 44 | self.tb = None 45 | 46 | def test_001_t(self): 47 | src = blocks.vector_source_c(range(10000), False, 1, []) 48 | separator = inspector.signal_separator_c(32000, window.WIN_HAMMING, 0.1, 100, False, 49 | {0.0: [0.0]}) 50 | vec_sink = blocks.vector_sink_c(1) 51 | ext = inspector.signal_extractor_c(0) 52 | snk = blocks.vector_sink_c(1) 53 | # pack message 54 | msg = pmt.make_vector(1, pmt.PMT_NIL) 55 | flanks = pmt.make_f32vector(2, 0.0) 56 | pmt.f32vector_set(flanks, 0, 12500) 57 | pmt.f32vector_set(flanks, 1, 20) 58 | pmt.vector_set(msg, 0, flanks) 59 | 60 | msg_src = blocks.message_strobe(msg, 100) 61 | 62 | taps = filter.firdes.low_pass( 63 | 1, 32000, 500, 50, window.WIN_HAMMING, 6.76) 64 | 65 | self.tb.connect(src, separator) 66 | self.tb.connect(src, vec_sink) 67 | self.tb.msg_connect((msg_src, 'strobe'), (separator, 'map_in')) 68 | self.tb.msg_connect((separator, 'sig_out'), (ext, 'sig_in')) 69 | self.tb.connect(ext, snk) 70 | 71 | self.tb.start() 72 | time.sleep(0.3) 73 | self.tb.stop() 74 | self.tb.wait() 75 | 76 | data = vec_sink.data() 77 | 78 | sig = numpy.zeros(len(vec_sink.data()), dtype=complex) 79 | for i in range(len(vec_sink.data())): 80 | sig[i] = data[i] * numpy.exp(-1j * 2 * numpy.pi * 12500 * i * 1 / 32000) 81 | 82 | taps = filter.firdes.low_pass( 83 | 1, 32000, 900, 90, window.WIN_HAMMING, 6.76) 84 | sig = numpy.convolve(sig, taps, 'full') 85 | out = numpy.empty([0]) 86 | decim = int(32000 / 20 / 100) 87 | j = 0 88 | for i in range(int(len(sig) // decim)): 89 | out = numpy.append(out, sig[j]) 90 | j += decim 91 | 92 | data = snk.data() 93 | for i in range(min(len(out), len(data))): 94 | self.assertComplexAlmostEqual2(out[i], data[i], abs_eps=0.01) 95 | 96 | 97 | if __name__ == '__main__': 98 | gr_unittest.run(qa_signal_separator_c) 99 | --------------------------------------------------------------------------------