├── .clang-format ├── .conda ├── README.md ├── conda-forge.yml └── recipe │ ├── bld.bat │ ├── build.sh │ ├── conda_build_config.yaml │ └── meta.yaml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── MANIFEST.md ├── README.md ├── cmake ├── Modules │ ├── CMakeParseArgumentsCopy.cmake │ ├── fooConfig.cmake │ └── targetConfig.cmake.in └── cmake_uninstall.cmake.in ├── docs ├── CMakeLists.txt ├── README.foo └── 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 │ ├── group_defs.dox │ └── main_page.dox │ ├── pydoc_macros.h │ └── update_pydoc.py ├── grc ├── CMakeLists.txt ├── foo_burst_tagger.block.yml ├── foo_channel_model.block.yml ├── foo_packet_dropper.block.yml ├── foo_packet_pad2.block.yml ├── foo_pad_tagged_stream.block.yml ├── foo_periodic_msg_source.block.yml ├── foo_random_periodic_msg_source.block.yml ├── foo_rtt_measure.block.yml ├── foo_selector.block.yml ├── foo_valve.block.yml └── foo_wireshark_connector.block.yml ├── include └── foo │ ├── CMakeLists.txt │ ├── api.h │ ├── burst_tagger.h │ ├── channel_model.h │ ├── packet_dropper.h │ ├── packet_pad2.h │ ├── pad_tagged_stream.h │ ├── periodic_msg_source.h │ ├── random_periodic_msg_source.h │ ├── rtt_measure.h │ └── wireshark_connector.h ├── lib ├── CMakeLists.txt ├── burst_tagger_impl.cc ├── burst_tagger_impl.h ├── channel_model_impl.cc ├── channel_model_impl.h ├── packet_dropper_impl.cc ├── packet_dropper_impl.h ├── packet_pad2.cc ├── pad_tagged_stream_impl.cc ├── pad_tagged_stream_impl.h ├── periodic_msg_source_impl.cc ├── periodic_msg_source_impl.h ├── random_periodic_msg_source_impl.cc ├── random_periodic_msg_source_impl.h ├── rtt_measure_impl.cc ├── rtt_measure_impl.h ├── wireshark_connector_impl.cc └── wireshark_connector_impl.h ├── python ├── CMakeLists.txt ├── __init__.py ├── bindings │ ├── CMakeLists.txt │ ├── README.md │ ├── bind_oot_file.py │ ├── burst_tagger_python.cc │ ├── channel_model_python.cc │ ├── docstrings │ │ ├── README.md │ │ ├── burst_tagger_pydoc_template.h │ │ ├── channel_model_pydoc_template.h │ │ ├── packet_dropper_pydoc_template.h │ │ ├── packet_pad2_pydoc_template.h │ │ ├── pad_tagged_stream_pydoc_template.h │ │ ├── periodic_msg_source_pydoc_template.h │ │ ├── random_periodic_msg_source_pydoc_template.h │ │ ├── rtt_measure_pydoc_template.h │ │ └── wireshark_connector_pydoc_template.h │ ├── header_utils.py │ ├── packet_dropper_python.cc │ ├── packet_pad2_python.cc │ ├── pad_tagged_stream_python.cc │ ├── periodic_msg_source_python.cc │ ├── python_bindings.cc │ ├── random_periodic_msg_source_python.cc │ ├── rtt_measure_python.cc │ └── wireshark_connector_python.cc └── selector.py └── utils └── gr-perf-to-csv /.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-foo 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 | linux_aarch64: linux_64 7 | linux_ppc64le: linux_64 8 | osx_arm64: osx_64 9 | clone_depth: 0 10 | conda_build: 11 | pkg_format: '2' 12 | github_actions: 13 | store_build_artifacts: true 14 | os_version: 15 | linux_64: cos7 16 | provider: 17 | linux: github_actions 18 | osx: github_actions 19 | win: github_actions 20 | # uncomment to enable additional linux platforms 21 | #linux_aarch64: github_actions 22 | #linux_ppc64le: github_actions 23 | recipe_dir: .conda/recipe 24 | # skip unnecessary files since this is not a full-fledged conda-forge feedstock 25 | skip_render: 26 | - README.md 27 | - LICENSE.txt 28 | - .gitattributes 29 | - .gitignore 30 | - build-locally.py 31 | - LICENSE 32 | test: native_and_emulated 33 | # enable uploads to Anaconda Cloud from specified branches only 34 | upload_on_branch: main 35 | -------------------------------------------------------------------------------- /.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 = "foo" %} 2 | {% set name = "gnuradio-" + oot_name %} 3 | # Set package version from cleaned up git tags if possible, 4 | # otherwise fall back to date-based version. 5 | {% set tag_version = environ.get("GIT_DESCRIBE_TAG", "")|string|replace("-","_")|replace("v","")|replace("git","") %} 6 | {% set post_commit = environ.get("GIT_DESCRIBE_NUMBER", 0)|string %} 7 | {% set hash = environ.get("GIT_DESCRIBE_HASH", "local")|string %} 8 | {% set fallback_version = "0.0.0.{0}.dev+g{1}".format(datetime.datetime.now().strftime("%Y%m%d"), environ.get("GIT_FULL_HASH", "local")[:9]) %} 9 | {% set version = (tag_version if post_commit == "0" else "{0}.post{1}+{2}".format(tag_version, post_commit, hash)) if tag_version else fallback_version %} 10 | 11 | package: 12 | name: {{ name|lower }} 13 | version: {{ version }} 14 | 15 | source: 16 | # use local path or git repository depending on if the build is local or done on CI 17 | path: "../.." # [not os.environ.get("CI")] 18 | git_url: {{ environ.get('FEEDSTOCK_ROOT', "../..") }} # [os.environ.get("CI")] 19 | 20 | build: 21 | number: 0 22 | run_exports: 23 | - {{ pin_subpackage('gnuradio-foo', max_pin='x.x.x') }} 24 | 25 | requirements: 26 | build: 27 | - {{ compiler("c") }} 28 | - {{ compiler("cxx") }} 29 | - cmake 30 | - git 31 | - ninja 32 | - pkg-config 33 | # cross-compilation requirements 34 | - python # [build_platform != target_platform] 35 | - cross-python_{{ target_platform }} # [build_platform != target_platform] 36 | - numpy # [build_platform != target_platform] 37 | - pybind11 # [build_platform != target_platform] 38 | 39 | host: 40 | - boost-cpp 41 | - gmp # [linux] 42 | # the following two entries are for generating builds against specific GR versions 43 | - gnuradio-core # [not gnuradio_extra_pin] 44 | - gnuradio-core {{ gnuradio_extra_pin }}.* # [gnuradio_extra_pin] 45 | - pip # [win] 46 | - pybind11 47 | - python 48 | - numpy 49 | - uhd 50 | 51 | run: 52 | - boost-cpp 53 | - numpy 54 | - python 55 | 56 | test: 57 | commands: 58 | # verify that (some) headers get installed 59 | - test -f $PREFIX/include/{{ oot_name }}/api.h # [not win] 60 | - if not exist %PREFIX%\\Library\\include\\{{ oot_name }}\\api.h exit 1 # [win] 61 | 62 | # verify that libraries get installed 63 | - test -f $PREFIX/lib/lib{{ name }}${SHLIB_EXT} # [not win] 64 | - if not exist %PREFIX%\\Library\\bin\\{{ name }}.dll exit 1 # [win] 65 | - if not exist %PREFIX%\\Library\\lib\\{{ name }}.lib exit 1 # [win] 66 | 67 | # verify that (some) GRC blocks get installed 68 | {% set blocks = ["burst_tagger", "channel_model", "packet_dropper", "packet_pad", "packet_pad2", "pad_tagged_stream", "periodic_msg_source", "random_periodic_msg_source", "selector", "valve", "wireshark_connector"] %} 69 | {% for block in blocks %} 70 | - test -f $PREFIX/share/gnuradio/grc/blocks/{{ oot_name }}_{{ block }}.block.yml # [not win] 71 | - if not exist %PREFIX%\\Library\\share\\gnuradio\\grc\\blocks\\{{ oot_name }}_{{ block }}.block.yml exit 1 # [win] 72 | {% endfor %} 73 | 74 | imports: 75 | # verify that the python module imports 76 | - {{ oot_name }} 77 | 78 | about: 79 | home: https://github.com/bastibl/gr-foo 80 | license: GPL-3.0-or-later 81 | license_file: LICENSE 82 | summary: Collection of GNU Radio blocks useful to other modules 83 | description: > 84 | This is a collection of custom blocks that are not directly associated with 85 | a project. For sample applications see: 86 | 87 | * https://github.com/bastibl/gr-ieee802-11 88 | * https://github.com/bastibl/gr-ieee802-15-4 89 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | *.pyo 4 | build*/ 5 | examples/grc/*.py 6 | -------------------------------------------------------------------------------- /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-foo 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Project setup 11 | ######################################################################## 12 | cmake_minimum_required(VERSION 3.8) 13 | project(gr-foo CXX C) 14 | enable_testing() 15 | 16 | # Install to PyBOMBS target prefix if defined 17 | if(DEFINED ENV{PYBOMBS_PREFIX}) 18 | set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX}) 19 | message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}") 20 | endif() 21 | 22 | # Select the release build type by default to get optimization flags 23 | if(NOT CMAKE_BUILD_TYPE) 24 | set(CMAKE_BUILD_TYPE "Release") 25 | message(STATUS "Build type not specified: defaulting to release.") 26 | endif(NOT CMAKE_BUILD_TYPE) 27 | set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") 28 | 29 | # Make sure our local CMake Modules path comes first 30 | list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) 31 | 32 | # Set the version information here 33 | set(VERSION_MAJOR 1) 34 | set(VERSION_API 1) 35 | set(VERSION_ABI 0) 36 | set(VERSION_PATCH git) 37 | 38 | cmake_policy(SET CMP0011 NEW) 39 | 40 | # Enable generation of compile_commands.json for code completion engines 41 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 42 | 43 | ######################################################################## 44 | # Compiler specific setup 45 | ######################################################################## 46 | if((CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR 47 | CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 48 | AND NOT WIN32) 49 | #http://gcc.gnu.org/wiki/Visibility 50 | add_definitions(-fvisibility=hidden) 51 | endif() 52 | 53 | IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 54 | SET(CMAKE_CXX_STANDARD 17) 55 | ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 56 | SET(CMAKE_CXX_STANDARD 17) 57 | ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 58 | SET(CMAKE_CXX_STANDARD 17) 59 | ELSE() 60 | message(WARNING "C++ standard could not be set because compiler is not GNU, Clang or MSVC.") 61 | ENDIF() 62 | 63 | IF(CMAKE_C_COMPILER_ID STREQUAL "GNU") 64 | SET(CMAKE_C_STANDARD 11) 65 | ELSEIF(CMAKE_C_COMPILER_ID MATCHES "Clang") 66 | SET(CMAKE_C_STANDARD 11) 67 | ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "MSVC") 68 | SET(CMAKE_C_STANDARD 11) 69 | ELSE() 70 | message(WARNING "C standard could not be set because compiler is not GNU, Clang or MSVC.") 71 | ENDIF() 72 | 73 | find_package(UHD) 74 | if(NOT UHD_FOUND) 75 | message(STATUS "UHD library not found, no support for timed TX.") 76 | set(UHD_INCLUDE_DIRS "") 77 | set(UHD_LIBRARY_DIRS "") 78 | set(UHD_LIBRARIES "") 79 | else() 80 | message(STATUS "UHD library found.") 81 | add_definitions(-DFOO_UHD) 82 | endif() 83 | 84 | ######################################################################## 85 | # Install directories 86 | ######################################################################## 87 | include(FindPkgConfig) 88 | find_package(Gnuradio "3.9" REQUIRED COMPONENTS blocks analog filter fft) 89 | include(GrVersion) 90 | 91 | include(GrPlatform) #define LIB_SUFFIX 92 | 93 | if(NOT CMAKE_MODULES_DIR) 94 | set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake) 95 | endif(NOT CMAKE_MODULES_DIR) 96 | 97 | set(GR_INCLUDE_DIR include/foo) 98 | set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/foo) 99 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) 100 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) 101 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) 102 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) 103 | 104 | ######################################################################## 105 | # On Apple only, set install name and use rpath correctly, if not already set 106 | ######################################################################## 107 | if(APPLE) 108 | if(NOT CMAKE_INSTALL_NAME_DIR) 109 | set(CMAKE_INSTALL_NAME_DIR 110 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 111 | PATH "Library Install Name Destination Directory" FORCE) 112 | endif(NOT CMAKE_INSTALL_NAME_DIR) 113 | if(NOT CMAKE_INSTALL_RPATH) 114 | set(CMAKE_INSTALL_RPATH 115 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 116 | PATH "Library Install RPath" FORCE) 117 | endif(NOT CMAKE_INSTALL_RPATH) 118 | if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 119 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE 120 | BOOL "Do Build Using Library Install RPath" FORCE) 121 | endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 122 | endif(APPLE) 123 | 124 | ######################################################################## 125 | # Find gnuradio build dependencies 126 | ######################################################################## 127 | find_package(Doxygen) 128 | 129 | ######################################################################## 130 | # Setup doxygen option 131 | ######################################################################## 132 | if(DOXYGEN_FOUND) 133 | option(ENABLE_DOXYGEN "Build docs using Doxygen" ON) 134 | else(DOXYGEN_FOUND) 135 | option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) 136 | endif(DOXYGEN_FOUND) 137 | 138 | ######################################################################## 139 | # Create uninstall target 140 | ######################################################################## 141 | configure_file( 142 | ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 143 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 144 | @ONLY) 145 | 146 | add_custom_target(uninstall 147 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 148 | ) 149 | 150 | ######################################################################## 151 | # Add subdirectories 152 | ######################################################################## 153 | add_subdirectory(include/foo) 154 | add_subdirectory(lib) 155 | add_subdirectory(docs) 156 | # NOTE: manually update below to use GRC to generate C++ flowgraphs w/o python 157 | if(ENABLE_PYTHON) 158 | message(STATUS "PYTHON and GRC components are enabled") 159 | add_subdirectory(python) 160 | add_subdirectory(grc) 161 | else(ENABLE_PYTHON) 162 | message(STATUS "PYTHON and GRC components are disabled") 163 | endif(ENABLE_PYTHON) 164 | 165 | ######################################################################## 166 | # Install cmake search helper for this library 167 | ######################################################################## 168 | 169 | install(FILES cmake/Modules/fooConfig.cmake 170 | DESTINATION ${CMAKE_MODULES_DIR}/foo 171 | ) 172 | -------------------------------------------------------------------------------- /MANIFEST.md: -------------------------------------------------------------------------------- 1 | title: gr-foo 2 | brief: some utility blocks 3 | tags: 4 | - foo 5 | author: 6 | - Bastian Bloessl 7 | copyright_owner: 8 | - Bastian Bloessl 9 | repo: https://github.com/bastibl/gr-foo.git 10 | website: https://github.com/bastibl/gr-foo 11 | icon: http://www.ccs-labs.org/projects/wime/wime.png 12 | gr_supported_version: v3.7, v3.8, v3.9 13 | --- 14 | This is a collection of custom blocks that are not directly associated with a project. For sample applications see: 15 | 16 | https://github.com/bastibl/gr-ieee802-11 17 | https://github.com/bastibl/gr-ieee802-15-4 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ____ \ 3 | ____ ______ / __/___ ____ \ \ 4 | / __ `/ ___/_____/ /_/ __ \/ __ \ \ | | 5 | / /_/ / / /_____/ __/ /_/ / /_/ / / | | 6 | \__, /_/ /_/ \____/\____/ / / 7 | /____/ / 8 | 9 | ``` 10 | 11 | Hi! 12 | 13 | This is a collection of custom blocks that are not directly associated with a 14 | project. For sample applications see: 15 | 16 | - https://github.com/bastibl/gr-ieee802-11 17 | - https://github.com/bastibl/gr-ieee802-15-4 18 | 19 | 20 | 21 | ### Development 22 | 23 | Like GNU Radio, this module uses *maint* branches for development. 24 | These branches are supposed to be used with the corresponding GNU Radio 25 | branches. This means: the *maint-3.7* branch is compatible with GNU Radio 3.7, 26 | *maint-3.8* is compatible with GNU Radio 3.8, etc. 27 | 28 | 29 | 30 | ### Wireshark Connector 31 | 32 | This blocks outputs PDUs in the PCAP format which is supported by all common 33 | network monitoring applications. Some examples are Wireshark, Tshark, and 34 | tcpdump. Currently, it supports WiFi packets with Radiotap header and ZigBee. 35 | 36 | For further information about Radiotap, PCAP, and Wireshark see: 37 | 38 | - http://www.radiotap.org/ 39 | - http://www.wireshark.org/ 40 | 41 | 42 | 43 | ### Packet Pad 44 | 45 | Adds a configurable number of zeros before and after a burst. The burst has to 46 | be started with an tx_sob, and ended with a tx_eob tag. From time to time I had 47 | issues when I did not pad the sample stream. This block helps to investigate 48 | that. It is also handy for loopback testing when there is no continues sample 49 | stream. Furthermore, this block can add a tx_time tag to every burst that lies 50 | a configurable number of seconds in the future. This is handy to buffer the 51 | sample stream for a short time to avoid underruns during the transmission, 52 | which lead to corrupted signals. You have to set the sync option to 'PC source' 53 | for this feature. 54 | 55 | 56 | 57 | ### Burst Tagger 58 | 59 | Tags a burst / packet / bunch of samples with tx_sob and tx_eob tags. This is 60 | useful if the SDR is operating in half-duplex mode. With adding a tx_eob the 61 | USRP switches back to receive mode immediately. That way, direct responses like 62 | ACKs are not missed. 63 | 64 | The block searches for a special tag that indicates the start of a burst. The 65 | name of this tag is configurable. The tag should indicate the length of the 66 | packet in samples. Also a multiplier can be specified, which multiples the 67 | length given in the tag. 68 | 69 | 70 | 71 | ### Packet Dropper 72 | 73 | Drops a configurable percentage of messages. I used it to test protocol logic 74 | like ACKs, retransmission and stuff. 75 | 76 | 77 | 78 | ### Periodic Msg Source 79 | 80 | This block sends messages at regular intervals much like the Message Strobe 81 | block in mainline GNU Radio. With this block you can also configure the number 82 | of packets that are sent. When all normal messages are sent, the blocks sends a 83 | final PMT_EOF message to indicate that it is done. 84 | I used this block for automated performance tests with no-GUI flow graphs. 85 | 86 | 87 | 88 | ### Pad Tagged Stream 89 | 90 | Pads an incoming tagged stream with 0s to the set buffer size. 91 | Padding is applied to the tail of the tagged stream. 92 | 93 | This is useful when transmitting packetized data by using a Pluto as SDR. 94 | The Pluto does currently not support a partial buffer flush triggered by an incoming tagged stream. 95 | Therefore this block pads incoming tagged stream to fill the Pluto buffer to enforce an immediate transmission. 96 | 97 | 98 | 99 | ### Installation 100 | 101 | ``` 102 | git clone https://github.com/bastibl/gr-foo.git 103 | cd gr-foo 104 | mkdir build 105 | cd build 106 | cmake .. 107 | make 108 | sudo make install 109 | sudo ldconfig 110 | ``` 111 | -------------------------------------------------------------------------------- /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/fooConfig.cmake: -------------------------------------------------------------------------------- 1 | if(NOT PKG_CONFIG_FOUND) 2 | INCLUDE(FindPkgConfig) 3 | endif() 4 | PKG_CHECK_MODULES(PC_FOO foo) 5 | 6 | FIND_PATH( 7 | FOO_INCLUDE_DIRS 8 | NAMES foo/api.h 9 | HINTS $ENV{FOO_DIR}/include 10 | ${PC_FOO_INCLUDEDIR} 11 | PATHS ${CMAKE_INSTALL_PREFIX}/include 12 | /usr/local/include 13 | /usr/include 14 | ) 15 | 16 | FIND_LIBRARY( 17 | FOO_LIBRARIES 18 | NAMES gnuradio-foo 19 | HINTS $ENV{FOO_DIR}/lib 20 | ${PC_FOO_LIBDIR} 21 | PATHS ${CMAKE_INSTALL_PREFIX}/lib 22 | ${CMAKE_INSTALL_PREFIX}/lib64 23 | /usr/local/lib 24 | /usr/local/lib64 25 | /usr/lib 26 | /usr/lib64 27 | ) 28 | 29 | include("${CMAKE_CURRENT_LIST_DIR}/fooTarget.cmake") 30 | 31 | INCLUDE(FindPackageHandleStandardArgs) 32 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(FOO DEFAULT_MSG FOO_LIBRARIES FOO_INCLUDE_DIRS) 33 | MARK_AS_ADVANCED(FOO_LIBRARIES FOO_INCLUDE_DIRS) 34 | -------------------------------------------------------------------------------- /cmake/Modules/targetConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Free Software Foundation, Inc. 2 | # 3 | # SPDX-License-Identifier: GPL-3.0-or-later 4 | # 5 | 6 | include(CMakeFindDependencyMacro) 7 | 8 | set(target_deps "@TARGET_DEPENDENCIES@") 9 | foreach(dep IN LISTS target_deps) 10 | find_dependency(${dep}) 11 | endforeach() 12 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGET@Targets.cmake") 13 | -------------------------------------------------------------------------------- /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-foo 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.foo: -------------------------------------------------------------------------------- 1 | This is the foo-write-a-block package meant as a guide to building 2 | out-of-tree packages. To use the foo blocks, the Python namespaces 3 | is in 'foo', which is imported as: 4 | 5 | import foo 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(foo) 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-foo 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-foo 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 | def _test(): 59 | import os 60 | this_dir = os.path.dirname(globals()['__file__']) 61 | xml_path = this_dir + "/example/xml/" 62 | di = DoxyIndex(xml_path) 63 | # Get the Aadvark class 64 | aad = di.get_member('Aadvark') 65 | aad.brief_description 66 | import doctest 67 | return doctest.testmod() 68 | 69 | if __name__ == "__main__": 70 | _test() 71 | 72 | -------------------------------------------------------------------------------- /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-foo 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/doxyindex.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-foo 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Classes providing more user-friendly interfaces to the doxygen xml 12 | docs than the generated classes provide. 13 | """ 14 | 15 | import os 16 | 17 | from .generated import index 18 | from .base import Base 19 | from .text import description 20 | 21 | class DoxyIndex(Base): 22 | """ 23 | Parses a doxygen xml directory. 24 | """ 25 | 26 | __module__ = "gnuradio.utils.doxyxml" 27 | 28 | def _parse(self): 29 | if self._parsed: 30 | return 31 | super(DoxyIndex, self)._parse() 32 | self._root = index.parse(os.path.join(self._xml_path, 'index.xml')) 33 | for mem in self._root.compound: 34 | converted = self.convert_mem(mem) 35 | # For files and namespaces we want the contents to be 36 | # accessible directly from the parent rather than having 37 | # to go through the file object. 38 | if self.get_cls(mem) == DoxyFile: 39 | if mem.name.endswith('.h'): 40 | self._members += converted.members() 41 | self._members.append(converted) 42 | elif self.get_cls(mem) == DoxyNamespace: 43 | self._members += converted.members() 44 | self._members.append(converted) 45 | else: 46 | self._members.append(converted) 47 | 48 | 49 | class DoxyCompMem(Base): 50 | 51 | 52 | kind = None 53 | 54 | def __init__(self, *args, **kwargs): 55 | super(DoxyCompMem, self).__init__(*args, **kwargs) 56 | 57 | @classmethod 58 | def can_parse(cls, obj): 59 | return obj.kind == cls.kind 60 | 61 | def set_descriptions(self, parse_data): 62 | bd = description(getattr(parse_data, 'briefdescription', None)) 63 | dd = description(getattr(parse_data, 'detaileddescription', None)) 64 | self._data['brief_description'] = bd 65 | self._data['detailed_description'] = dd 66 | 67 | def set_parameters(self, data): 68 | vs = [ddc.value for ddc in data.detaileddescription.content_] 69 | pls = [] 70 | for v in vs: 71 | if hasattr(v, 'parameterlist'): 72 | pls += v.parameterlist 73 | pis = [] 74 | for pl in pls: 75 | pis += pl.parameteritem 76 | dpis = [] 77 | for pi in pis: 78 | dpi = DoxyParameterItem(pi) 79 | dpi._parse() 80 | dpis.append(dpi) 81 | self._data['params'] = dpis 82 | 83 | 84 | class DoxyCompound(DoxyCompMem): 85 | pass 86 | 87 | class DoxyMember(DoxyCompMem): 88 | pass 89 | 90 | class DoxyFunction(DoxyMember): 91 | 92 | __module__ = "gnuradio.utils.doxyxml" 93 | 94 | kind = 'function' 95 | 96 | def _parse(self): 97 | if self._parsed: 98 | return 99 | super(DoxyFunction, self)._parse() 100 | self.set_descriptions(self._parse_data) 101 | self.set_parameters(self._parse_data) 102 | if not self._data['params']: 103 | # If the params weren't set by a comment then just grab the names. 104 | self._data['params'] = [] 105 | prms = self._parse_data.param 106 | for prm in prms: 107 | self._data['params'].append(DoxyParam(prm)) 108 | 109 | brief_description = property(lambda self: self.data()['brief_description']) 110 | detailed_description = property(lambda self: self.data()['detailed_description']) 111 | params = property(lambda self: self.data()['params']) 112 | 113 | Base.mem_classes.append(DoxyFunction) 114 | 115 | 116 | class DoxyParam(DoxyMember): 117 | 118 | __module__ = "gnuradio.utils.doxyxml" 119 | 120 | def _parse(self): 121 | if self._parsed: 122 | return 123 | super(DoxyParam, self)._parse() 124 | self.set_descriptions(self._parse_data) 125 | self._data['declname'] = self._parse_data.declname 126 | 127 | @property 128 | def description(self): 129 | descriptions = [] 130 | if self.brief_description: 131 | descriptions.append(self.brief_description) 132 | if self.detailed_description: 133 | descriptions.append(self.detailed_description) 134 | return '\n\n'.join(descriptions) 135 | 136 | brief_description = property(lambda self: self.data()['brief_description']) 137 | detailed_description = property(lambda self: self.data()['detailed_description']) 138 | name = property(lambda self: self.data()['declname']) 139 | 140 | class DoxyParameterItem(DoxyMember): 141 | """A different representation of a parameter in Doxygen.""" 142 | 143 | def _parse(self): 144 | if self._parsed: 145 | return 146 | super(DoxyParameterItem, self)._parse() 147 | names = [] 148 | for nl in self._parse_data.parameternamelist: 149 | for pn in nl.parametername: 150 | names.append(description(pn)) 151 | # Just take first name 152 | self._data['name'] = names[0] 153 | # Get description 154 | pd = description(self._parse_data.get_parameterdescription()) 155 | self._data['description'] = pd 156 | 157 | description = property(lambda self: self.data()['description']) 158 | name = property(lambda self: self.data()['name']) 159 | 160 | 161 | class DoxyClass(DoxyCompound): 162 | 163 | __module__ = "gnuradio.utils.doxyxml" 164 | 165 | kind = 'class' 166 | 167 | def _parse(self): 168 | if self._parsed: 169 | return 170 | super(DoxyClass, self)._parse() 171 | self.retrieve_data() 172 | if self._error: 173 | return 174 | self.set_descriptions(self._retrieved_data.compounddef) 175 | self.set_parameters(self._retrieved_data.compounddef) 176 | # Sectiondef.kind tells about whether private or public. 177 | # We just ignore this for now. 178 | self.process_memberdefs() 179 | 180 | brief_description = property(lambda self: self.data()['brief_description']) 181 | detailed_description = property(lambda self: self.data()['detailed_description']) 182 | params = property(lambda self: self.data()['params']) 183 | 184 | Base.mem_classes.append(DoxyClass) 185 | 186 | 187 | class DoxyFile(DoxyCompound): 188 | 189 | __module__ = "gnuradio.utils.doxyxml" 190 | 191 | kind = 'file' 192 | 193 | def _parse(self): 194 | if self._parsed: 195 | return 196 | super(DoxyFile, self)._parse() 197 | self.retrieve_data() 198 | self.set_descriptions(self._retrieved_data.compounddef) 199 | if self._error: 200 | return 201 | self.process_memberdefs() 202 | 203 | brief_description = property(lambda self: self.data()['brief_description']) 204 | detailed_description = property(lambda self: self.data()['detailed_description']) 205 | 206 | Base.mem_classes.append(DoxyFile) 207 | 208 | 209 | class DoxyNamespace(DoxyCompound): 210 | 211 | __module__ = "gnuradio.utils.doxyxml" 212 | 213 | kind = 'namespace' 214 | 215 | def _parse(self): 216 | if self._parsed: 217 | return 218 | super(DoxyNamespace, self)._parse() 219 | self.retrieve_data() 220 | self.set_descriptions(self._retrieved_data.compounddef) 221 | if self._error: 222 | return 223 | self.process_memberdefs() 224 | 225 | Base.mem_classes.append(DoxyNamespace) 226 | 227 | 228 | class DoxyGroup(DoxyCompound): 229 | 230 | __module__ = "gnuradio.utils.doxyxml" 231 | 232 | kind = 'group' 233 | 234 | def _parse(self): 235 | if self._parsed: 236 | return 237 | super(DoxyGroup, self)._parse() 238 | self.retrieve_data() 239 | if self._error: 240 | return 241 | cdef = self._retrieved_data.compounddef 242 | self._data['title'] = description(cdef.title) 243 | # Process inner groups 244 | grps = cdef.innergroup 245 | for grp in grps: 246 | converted = DoxyGroup.from_refid(grp.refid, top=self.top) 247 | self._members.append(converted) 248 | # Process inner classes 249 | klasses = cdef.innerclass 250 | for kls in klasses: 251 | converted = DoxyClass.from_refid(kls.refid, top=self.top) 252 | self._members.append(converted) 253 | # Process normal members 254 | self.process_memberdefs() 255 | 256 | title = property(lambda self: self.data()['title']) 257 | 258 | 259 | Base.mem_classes.append(DoxyGroup) 260 | 261 | 262 | class DoxyFriend(DoxyMember): 263 | 264 | __module__ = "gnuradio.utils.doxyxml" 265 | 266 | kind = 'friend' 267 | 268 | Base.mem_classes.append(DoxyFriend) 269 | 270 | 271 | class DoxyOther(Base): 272 | 273 | __module__ = "gnuradio.utils.doxyxml" 274 | 275 | kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum', 276 | 'dir', 'page', 'signal', 'slot', 'property']) 277 | 278 | @classmethod 279 | def can_parse(cls, obj): 280 | return obj.kind in cls.kinds 281 | 282 | Base.mem_classes.append(DoxyOther) 283 | -------------------------------------------------------------------------------- /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 | class DoxygenTypeSub(supermod.DoxygenType): 16 | def __init__(self, version=None, compound=None): 17 | supermod.DoxygenType.__init__(self, version, compound) 18 | 19 | def find_compounds_and_members(self, details): 20 | """ 21 | Returns a list of all compounds and their members which match details 22 | """ 23 | 24 | results = [] 25 | for compound in self.compound: 26 | members = compound.find_members(details) 27 | if members: 28 | results.append([compound, members]) 29 | else: 30 | if details.match(compound): 31 | results.append([compound, []]) 32 | 33 | return results 34 | 35 | supermod.DoxygenType.subclass = DoxygenTypeSub 36 | # end class DoxygenTypeSub 37 | 38 | 39 | class CompoundTypeSub(supermod.CompoundType): 40 | def __init__(self, kind=None, refid=None, name='', member=None): 41 | supermod.CompoundType.__init__(self, kind, refid, name, member) 42 | 43 | def find_members(self, details): 44 | """ 45 | Returns a list of all members which match details 46 | """ 47 | 48 | results = [] 49 | 50 | for member in self.member: 51 | if details.match(member): 52 | results.append(member) 53 | 54 | return results 55 | 56 | supermod.CompoundType.subclass = CompoundTypeSub 57 | # end class CompoundTypeSub 58 | 59 | 60 | class MemberTypeSub(supermod.MemberType): 61 | 62 | def __init__(self, kind=None, refid=None, name=''): 63 | supermod.MemberType.__init__(self, kind, refid, name) 64 | 65 | supermod.MemberType.subclass = MemberTypeSub 66 | # end class MemberTypeSub 67 | 68 | 69 | def parse(inFilename): 70 | 71 | doc = minidom.parse(inFilename) 72 | rootNode = doc.documentElement 73 | rootObj = supermod.DoxygenType.factory() 74 | rootObj.build(rootNode) 75 | 76 | return rootObj 77 | 78 | -------------------------------------------------------------------------------- /docs/doxygen/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-foo 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Utilities for extracting text from generated classes. 12 | """ 13 | 14 | def is_string(txt): 15 | if isinstance(txt, str): 16 | return True 17 | try: 18 | if isinstance(txt, str): 19 | return True 20 | except NameError: 21 | pass 22 | return False 23 | 24 | def description(obj): 25 | if obj is None: 26 | return None 27 | return description_bit(obj).strip() 28 | 29 | def description_bit(obj): 30 | if hasattr(obj, 'content'): 31 | contents = [description_bit(item) for item in obj.content] 32 | result = ''.join(contents) 33 | elif hasattr(obj, 'content_'): 34 | contents = [description_bit(item) for item in obj.content_] 35 | result = ''.join(contents) 36 | elif hasattr(obj, 'value'): 37 | result = description_bit(obj.value) 38 | elif is_string(obj): 39 | return obj 40 | else: 41 | raise Exception('Expecting a string or something with content, content_ or value attribute') 42 | # If this bit is a paragraph then add one some line breaks. 43 | if hasattr(obj, 'name') and obj.name == 'para': 44 | result += "\n\n" 45 | return result 46 | -------------------------------------------------------------------------------- /docs/doxygen/other/group_defs.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | * \defgroup block GNU Radio FOO C++ Signal Processing Blocks 3 | * \brief All C++ blocks that can be used from the FOO GNU Radio 4 | * module are listed here or in the subcategories below. 5 | * 6 | */ 7 | 8 | -------------------------------------------------------------------------------- /docs/doxygen/other/main_page.dox: -------------------------------------------------------------------------------- 1 | /*! \mainpage 2 | 3 | Welcome to the GNU Radio FOO Block 4 | 5 | This is the intro page for the Doxygen manual generated for the FOO 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 -------------------------------------------------------------------------------- /docs/doxygen/update_pydoc.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2010-2012 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 gnuradio 6 | # 7 | # SPDX-License-Identifier: GPL-3.0-or-later 8 | # 9 | # 10 | """ 11 | Updates the *pydoc_h files for a module 12 | Execute using: python update_pydoc.py xml_path outputfilename 13 | 14 | The file instructs Pybind11 to transfer the doxygen comments into the 15 | python docstrings. 16 | 17 | """ 18 | 19 | import os, sys, time, glob, re, json 20 | from argparse import ArgumentParser 21 | 22 | from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile 23 | from doxyxml import DoxyOther, base 24 | 25 | def py_name(name): 26 | bits = name.split('_') 27 | return '_'.join(bits[1:]) 28 | 29 | def make_name(name): 30 | bits = name.split('_') 31 | return bits[0] + '_make_' + '_'.join(bits[1:]) 32 | 33 | 34 | class Block(object): 35 | """ 36 | Checks if doxyxml produced objects correspond to a gnuradio block. 37 | """ 38 | 39 | @classmethod 40 | def includes(cls, item): 41 | if not isinstance(item, DoxyClass): 42 | return False 43 | # Check for a parsing error. 44 | if item.error(): 45 | return False 46 | friendname = make_name(item.name()) 47 | is_a_block = item.has_member(friendname, DoxyFriend) 48 | # But now sometimes the make function isn't a friend so check again. 49 | if not is_a_block: 50 | is_a_block = di.has_member(friendname, DoxyFunction) 51 | return is_a_block 52 | 53 | class Block2(object): 54 | """ 55 | Checks if doxyxml produced objects correspond to a new style 56 | gnuradio block. 57 | """ 58 | 59 | @classmethod 60 | def includes(cls, item): 61 | if not isinstance(item, DoxyClass): 62 | return False 63 | # Check for a parsing error. 64 | if item.error(): 65 | return False 66 | is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther) 67 | return is_a_block2 68 | 69 | 70 | def utoascii(text): 71 | """ 72 | Convert unicode text into ascii and escape quotes and backslashes. 73 | """ 74 | if text is None: 75 | return '' 76 | out = text.encode('ascii', 'replace') 77 | # swig will require us to replace blackslash with 4 backslashes 78 | # TODO: evaluate what this should be for pybind11 79 | out = out.replace(b'\\', b'\\\\\\\\') 80 | out = out.replace(b'"', b'\\"').decode('ascii') 81 | return str(out) 82 | 83 | 84 | def combine_descriptions(obj): 85 | """ 86 | Combines the brief and detailed descriptions of an object together. 87 | """ 88 | description = [] 89 | bd = obj.brief_description.strip() 90 | dd = obj.detailed_description.strip() 91 | if bd: 92 | description.append(bd) 93 | if dd: 94 | description.append(dd) 95 | return utoascii('\n\n'.join(description)).strip() 96 | 97 | def format_params(parameteritems): 98 | output = ['Args:'] 99 | template = ' {0} : {1}' 100 | for pi in parameteritems: 101 | output.append(template.format(pi.name, pi.description)) 102 | return '\n'.join(output) 103 | 104 | entry_templ = '%feature("docstring") {name} "{docstring}"' 105 | def make_entry(obj, name=None, templ="{description}", description=None, params=[]): 106 | """ 107 | Create a docstring key/value pair, where the key is the object name. 108 | 109 | obj - a doxyxml object from which documentation will be extracted. 110 | name - the name of the C object (defaults to obj.name()) 111 | templ - an optional template for the docstring containing only one 112 | variable named 'description'. 113 | description - if this optional variable is set then it's value is 114 | used as the description instead of extracting it from obj. 115 | """ 116 | if name is None: 117 | name=obj.name() 118 | if hasattr(obj,'_parse_data') and hasattr(obj._parse_data,'definition'): 119 | name=obj._parse_data.definition.split(' ')[-1] 120 | if "operator " in name: 121 | return '' 122 | if description is None: 123 | description = combine_descriptions(obj) 124 | if params: 125 | description += '\n\n' 126 | description += utoascii(format_params(params)) 127 | docstring = templ.format(description=description) 128 | 129 | return {name: docstring} 130 | 131 | 132 | def make_class_entry(klass, description=None, ignored_methods=[], params=None): 133 | """ 134 | Create a class docstring key/value pair. 135 | """ 136 | if params is None: 137 | params = klass.params 138 | output = {} 139 | output.update(make_entry(klass, description=description, params=params)) 140 | for func in klass.in_category(DoxyFunction): 141 | if func.name() not in ignored_methods: 142 | name = klass.name() + '::' + func.name() 143 | output.update(make_entry(func, name=name)) 144 | return output 145 | 146 | 147 | def make_block_entry(di, block): 148 | """ 149 | Create class and function docstrings of a gnuradio block 150 | """ 151 | descriptions = [] 152 | # Get the documentation associated with the class. 153 | class_desc = combine_descriptions(block) 154 | if class_desc: 155 | descriptions.append(class_desc) 156 | # Get the documentation associated with the make function 157 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 158 | make_func_desc = combine_descriptions(make_func) 159 | if make_func_desc: 160 | descriptions.append(make_func_desc) 161 | # Get the documentation associated with the file 162 | try: 163 | block_file = di.get_member(block.name() + ".h", DoxyFile) 164 | file_desc = combine_descriptions(block_file) 165 | if file_desc: 166 | descriptions.append(file_desc) 167 | except base.Base.NoSuchMember: 168 | # Don't worry if we can't find a matching file. 169 | pass 170 | # And join them all together to make a super duper description. 171 | super_description = "\n\n".join(descriptions) 172 | # Associate the combined description with the class and 173 | # the make function. 174 | output = {} 175 | output.update(make_class_entry(block, description=super_description)) 176 | output.update(make_entry(make_func, description=super_description, 177 | params=block.params)) 178 | return output 179 | 180 | def make_block2_entry(di, block): 181 | """ 182 | Create class and function docstrings of a new style gnuradio block 183 | """ 184 | # For new style blocks all the relevant documentation should be 185 | # associated with the 'make' method. 186 | class_description = combine_descriptions(block) 187 | make_func = block.get_member('make', DoxyFunction) 188 | make_description = combine_descriptions(make_func) 189 | description = class_description + "\n\nConstructor Specific Documentation:\n\n" + make_description 190 | # Associate the combined description with the class and 191 | # the make function. 192 | output = {} 193 | output.update(make_class_entry( 194 | block, description=description, 195 | ignored_methods=['make'], params=make_func.params)) 196 | makename = block.name() + '::make' 197 | output.update(make_entry( 198 | make_func, name=makename, description=description, 199 | params=make_func.params)) 200 | return output 201 | 202 | def get_docstrings_dict(di, custom_output=None): 203 | 204 | output = {} 205 | if custom_output: 206 | output.update(custom_output) 207 | 208 | # Create docstrings for the blocks. 209 | blocks = di.in_category(Block) 210 | blocks2 = di.in_category(Block2) 211 | 212 | make_funcs = set([]) 213 | for block in blocks: 214 | try: 215 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 216 | # Don't want to risk writing to output twice. 217 | if make_func.name() not in make_funcs: 218 | make_funcs.add(make_func.name()) 219 | output.update(make_block_entry(di, block)) 220 | except block.ParsingError: 221 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) 222 | raise 223 | 224 | for block in blocks2: 225 | try: 226 | make_func = block.get_member('make', DoxyFunction) 227 | make_func_name = block.name() +'::make' 228 | # Don't want to risk writing to output twice. 229 | if make_func_name not in make_funcs: 230 | make_funcs.add(make_func_name) 231 | output.update(make_block2_entry(di, block)) 232 | except block.ParsingError: 233 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) 234 | raise 235 | 236 | # Create docstrings for functions 237 | # Don't include the make functions since they have already been dealt with. 238 | funcs = [f for f in di.in_category(DoxyFunction) 239 | if f.name() not in make_funcs and not f.name().startswith('std::')] 240 | for f in funcs: 241 | try: 242 | output.update(make_entry(f)) 243 | except f.ParsingError: 244 | sys.stderr.write('Parsing error for function {0}\n'.format(f.name())) 245 | 246 | # Create docstrings for classes 247 | block_names = [block.name() for block in blocks] 248 | block_names += [block.name() for block in blocks2] 249 | klasses = [k for k in di.in_category(DoxyClass) 250 | if k.name() not in block_names and not k.name().startswith('std::')] 251 | for k in klasses: 252 | try: 253 | output.update(make_class_entry(k)) 254 | except k.ParsingError: 255 | sys.stderr.write('Parsing error for class {0}\n'.format(k.name())) 256 | 257 | # Docstrings are not created for anything that is not a function or a class. 258 | # If this excludes anything important please add it here. 259 | 260 | return output 261 | 262 | def sub_docstring_in_pydoc_h(pydoc_files, docstrings_dict, output_dir, filter_str=None): 263 | if filter_str: 264 | docstrings_dict = {k: v for k, v in docstrings_dict.items() if k.startswith(filter_str)} 265 | 266 | with open(os.path.join(output_dir,'docstring_status'),'w') as status_file: 267 | 268 | for pydoc_file in pydoc_files: 269 | if filter_str: 270 | filter_str2 = "::".join((filter_str,os.path.split(pydoc_file)[-1].split('_pydoc_template.h')[0])) 271 | docstrings_dict2 = {k: v for k, v in docstrings_dict.items() if k.startswith(filter_str2)} 272 | else: 273 | docstrings_dict2 = docstrings_dict 274 | 275 | 276 | 277 | file_in = open(pydoc_file,'r').read() 278 | for key, value in docstrings_dict2.items(): 279 | file_in_tmp = file_in 280 | try: 281 | doc_key = key.split("::") 282 | # if 'gr' in doc_key: 283 | # doc_key.remove('gr') 284 | doc_key = '_'.join(doc_key) 285 | regexp = r'(__doc_{} =\sR\"doc\()[^)]*(\)doc\")'.format(doc_key) 286 | regexp = re.compile(regexp, re.MULTILINE) 287 | 288 | (file_in, nsubs) = regexp.subn(r'\1'+value+r'\2', file_in, count=1) 289 | if nsubs == 1: 290 | status_file.write("PASS: " + pydoc_file + "\n") 291 | except KeyboardInterrupt: 292 | raise KeyboardInterrupt 293 | except: # be permissive, TODO log, but just leave the docstring blank 294 | status_file.write("FAIL: " + pydoc_file + "\n") 295 | file_in = file_in_tmp 296 | 297 | output_pathname = os.path.join(output_dir, os.path.basename(pydoc_file).replace('_template.h','.h')) 298 | # FIXME: Remove this debug print 299 | print('output docstrings to {}'.format(output_pathname)) 300 | with open(output_pathname,'w') as file_out: 301 | file_out.write(file_in) 302 | 303 | def copy_docstring_templates(pydoc_files, output_dir): 304 | with open(os.path.join(output_dir,'docstring_status'),'w') as status_file: 305 | for pydoc_file in pydoc_files: 306 | file_in = open(pydoc_file,'r').read() 307 | output_pathname = os.path.join(output_dir, os.path.basename(pydoc_file).replace('_template.h','.h')) 308 | # FIXME: Remove this debug print 309 | print('copy docstrings to {}'.format(output_pathname)) 310 | with open(output_pathname,'w') as file_out: 311 | file_out.write(file_in) 312 | status_file.write("DONE") 313 | 314 | def argParse(): 315 | """Parses commandline args.""" 316 | desc='Scrape the doxygen generated xml for docstrings to insert into python bindings' 317 | parser = ArgumentParser(description=desc) 318 | 319 | parser.add_argument("function", help="Operation to perform on docstrings", choices=["scrape","sub","copy"]) 320 | 321 | parser.add_argument("--xml_path") 322 | parser.add_argument("--bindings_dir") 323 | parser.add_argument("--output_dir") 324 | parser.add_argument("--json_path") 325 | parser.add_argument("--filter", default=None) 326 | 327 | return parser.parse_args() 328 | 329 | if __name__ == "__main__": 330 | # Parse command line options and set up doxyxml. 331 | args = argParse() 332 | if args.function.lower() == 'scrape': 333 | di = DoxyIndex(args.xml_path) 334 | docstrings_dict = get_docstrings_dict(di) 335 | with open(args.json_path, 'w') as fp: 336 | json.dump(docstrings_dict, fp) 337 | elif args.function.lower() == 'sub': 338 | with open(args.json_path, 'r') as fp: 339 | docstrings_dict = json.load(fp) 340 | pydoc_files = glob.glob(os.path.join(args.bindings_dir,'*_pydoc_template.h')) 341 | sub_docstring_in_pydoc_h(pydoc_files, docstrings_dict, args.output_dir, args.filter) 342 | elif args.function.lower() == 'copy': 343 | pydoc_files = glob.glob(os.path.join(args.bindings_dir,'*_pydoc_template.h')) 344 | copy_docstring_templates(pydoc_files, args.output_dir) 345 | 346 | 347 | -------------------------------------------------------------------------------- /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-foo 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | install(FILES 10 | foo_burst_tagger.block.yml 11 | foo_packet_pad2.block.yml 12 | foo_random_periodic_msg_source.block.yml 13 | foo_valve.block.yml 14 | foo_channel_model.block.yml 15 | foo_rtt_measure.block.yml 16 | foo_wireshark_connector.block.yml 17 | foo_packet_dropper.block.yml 18 | foo_periodic_msg_source.block.yml 19 | foo_selector.block.yml 20 | foo_pad_tagged_stream.block.yml 21 | DESTINATION share/gnuradio/grc/blocks 22 | ) 23 | -------------------------------------------------------------------------------- /grc/foo_burst_tagger.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_burst_tagger 4 | label: Burst Tagger 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: tag_name 9 | label: Tag Name 10 | dtype: raw 11 | default: pmt.intern("burst_len") 12 | - id: mult 13 | label: Multiplier 14 | dtype: int 15 | default: '1' 16 | 17 | inputs: 18 | - domain: stream 19 | dtype: complex 20 | 21 | outputs: 22 | - domain: stream 23 | dtype: complex 24 | asserts: 25 | - ${ mult > 0 } 26 | 27 | templates: 28 | imports: |- 29 | import pmt 30 | import foo 31 | make: foo.burst_tagger(${tag_name}, ${mult}) 32 | 33 | file_format: 1 34 | -------------------------------------------------------------------------------- /grc/foo_channel_model.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_channel_model 4 | label: Channel Model 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: noise_voltage 9 | label: Noise Voltage 10 | dtype: real 11 | default: '0.0' 12 | - id: freq_offset 13 | label: Frequency Offset 14 | dtype: real 15 | default: '0.0' 16 | - id: epsilon 17 | label: Epsilon 18 | dtype: real 19 | default: '1.0' 20 | - id: taps 21 | label: Taps 22 | dtype: complex_vector 23 | default: 1.0 + 1.0j 24 | - id: seed 25 | label: Seed 26 | dtype: int 27 | default: '0' 28 | - id: block_tags 29 | label: Block Tag Propagation 30 | dtype: enum 31 | default: 'False' 32 | options: ['True', 'False'] 33 | option_labels: ['Yes', 'No'] 34 | option_attributes: 35 | hide_block: ['', part] 36 | hide: ${ block_tags.hide_block } 37 | 38 | inputs: 39 | - domain: stream 40 | dtype: complex 41 | 42 | outputs: 43 | - domain: stream 44 | dtype: complex 45 | 46 | templates: 47 | imports: import foo 48 | make: "foo.channel_model(\n\tnoise_voltage=${noise_voltage},\n\tfrequency_offset=${freq_offset},\n\ 49 | \tepsilon=${epsilon},\n\ttaps=${taps},\n\tnoise_seed=${seed},\n\tblock_tags=${block_tags}\n\ 50 | )" 51 | callbacks: 52 | - set_noise_voltage(${noise_voltage}) 53 | - set_frequency_offset(${freq_offset}) 54 | - set_taps(${taps}) 55 | - set_timing_offset(${epsilon}) 56 | 57 | file_format: 1 58 | -------------------------------------------------------------------------------- /grc/foo_packet_dropper.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_packet_dropper 4 | label: Packet Dropper 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: drop_rate 9 | label: Packet drop rate 10 | dtype: real 11 | default: '0.5' 12 | - id: seed 13 | label: Random seed 14 | dtype: int 15 | default: '42' 16 | 17 | inputs: 18 | - domain: message 19 | id: in 20 | 21 | outputs: 22 | - domain: message 23 | id: out 24 | 25 | templates: 26 | imports: import foo 27 | make: foo.packet_dropper(${drop_rate}, ${seed}) 28 | 29 | file_format: 1 30 | -------------------------------------------------------------------------------- /grc/foo_packet_pad2.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_packet_pad2 4 | label: Packet Pad2 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: debug 9 | label: Debug 10 | dtype: bool 11 | default: 'False' 12 | options: ['True', 'False'] 13 | option_labels: [Enable, Disable] 14 | - id: delay 15 | label: Delay 16 | dtype: bool 17 | default: 'False' 18 | options: ['True', 'False'] 19 | option_labels: [Enable, Disable] 20 | - id: delay_sec 21 | label: Delay Sec 22 | dtype: real 23 | default: '0.001' 24 | - id: pad_front 25 | label: Pad Front 26 | dtype: int 27 | default: '0' 28 | - id: pad_tail 29 | label: Pad Tail 30 | dtype: int 31 | default: '0' 32 | 33 | inputs: 34 | - domain: stream 35 | dtype: complex 36 | multiplicity: '1' 37 | 38 | outputs: 39 | - domain: stream 40 | dtype: complex 41 | multiplicity: '1' 42 | asserts: 43 | - ${ pad_front >= 0 } 44 | - ${ pad_tail >= 0 } 45 | - ${ delay_sec > 0 } 46 | 47 | templates: 48 | imports: import foo 49 | make: foo.packet_pad2(${debug}, ${delay}, ${delay_sec}, ${pad_front}, ${pad_tail}) 50 | 51 | file_format: 1 52 | -------------------------------------------------------------------------------- /grc/foo_pad_tagged_stream.block.yml: -------------------------------------------------------------------------------- 1 | id: foo_pad_tagged_stream 2 | label: Pad Tagged Stream 3 | category: '[Foo]' 4 | 5 | templates: 6 | imports: import foo 7 | make: foo.pad_tagged_stream(${buffer_size}, ${len_tag_name}) 8 | 9 | # Make one 'parameters' list entry for every parameter you want settable from the GUI. 10 | # Keys include: 11 | # * id (makes the value accessible as \$keyname, e.g. in the make entry) 12 | # * label (label shown in the GUI) 13 | # * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) 14 | parameters: 15 | - id: buffer_size 16 | label: Buffer Size 17 | dtype: int 18 | default: '0x8000' 19 | - id: len_tag_name 20 | label: Length Tag Key 21 | dtype: string 22 | 23 | # Make one 'inputs' list entry per input and one 'outputs' list entry per output. 24 | # Keys include: 25 | # * label (an identifier for the GUI) 26 | # * domain (optional - stream or message. Default is stream) 27 | # * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) 28 | # * vlen (optional - data stream vector length. Default is 1) 29 | # * optional (optional - set to 1 for optional inputs. Default is 0) 30 | inputs: 31 | - label: in 32 | domain: stream 33 | dtype: complex 34 | vlen: 1 35 | optional: 0 36 | 37 | outputs: 38 | - label: out 39 | domain: stream 40 | dtype: complex 41 | vlen: 1 42 | optional: 0 43 | 44 | # 'file_format' specifies the version of the GRC yml format used in the file 45 | # and should usually not be changed. 46 | file_format: 1 47 | -------------------------------------------------------------------------------- /grc/foo_periodic_msg_source.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_periodic_msg_source 4 | label: Periodic Message Source 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: msg 9 | label: Message PMT 10 | dtype: raw 11 | default: pmt.intern("Hello World!") 12 | - id: interval 13 | label: Period (ms) 14 | dtype: int 15 | default: '1000' 16 | - id: quit 17 | label: Quit 18 | dtype: bool 19 | default: 'True' 20 | options: ['True', 'False'] 21 | option_labels: [Enable, Disable] 22 | - id: debug 23 | label: Debug 24 | dtype: bool 25 | default: 'False' 26 | options: ['True', 'False'] 27 | option_labels: [Enable, Disable] 28 | - id: num 29 | label: Num Messages 30 | dtype: int 31 | default: '-1' 32 | 33 | outputs: 34 | - domain: message 35 | id: out 36 | optional: true 37 | 38 | templates: 39 | imports: |- 40 | import foo 41 | import pmt 42 | make: foo.periodic_msg_source(${msg}, ${interval}, ${num}, ${quit}, ${debug}) 43 | 44 | file_format: 1 45 | -------------------------------------------------------------------------------- /grc/foo_random_periodic_msg_source.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_random_periodic_msg_source 4 | label: Random Periodic Message Source 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: msg_len 9 | label: Message Length 10 | dtype: int 11 | default: '64' 12 | - id: interval 13 | label: Period (ms) 14 | dtype: int 15 | default: '1000' 16 | - id: quit 17 | label: Quit 18 | dtype: bool 19 | default: 'True' 20 | options: ['True', 'False'] 21 | option_labels: [Enable, Disable] 22 | - id: debug 23 | label: Debug 24 | dtype: bool 25 | default: 'False' 26 | options: ['True', 'False'] 27 | option_labels: [Enable, Disable] 28 | - id: num 29 | label: Num Messages 30 | dtype: int 31 | default: '1' 32 | - id: seed 33 | label: Random Seed 34 | dtype: int 35 | default: '1' 36 | 37 | outputs: 38 | - domain: message 39 | id: out 40 | optional: true 41 | 42 | templates: 43 | imports: |- 44 | import foo 45 | import pmt 46 | make: foo.random_periodic_msg_source(${msg_len}, ${interval}, ${num}, ${quit}, 47 | ${debug}, ${seed}) 48 | 49 | file_format: 1 50 | -------------------------------------------------------------------------------- /grc/foo_rtt_measure.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_rtt_measure 4 | label: RTT measure 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: interval 9 | label: Send interval 10 | dtype: int 11 | default: '500' 12 | 13 | inputs: 14 | - domain: message 15 | id: in 16 | 17 | outputs: 18 | - label: dout 19 | domain: stream 20 | dtype: byte 21 | - domain: message 22 | id: out 23 | 24 | templates: 25 | imports: import foo 26 | make: foo.rtt_measure(${interval}) 27 | 28 | file_format: 1 29 | -------------------------------------------------------------------------------- /grc/foo_selector.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_selector 4 | label: Selector 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [complex, float, int, short, byte] 12 | option_attributes: 13 | size: [gr.sizeof_gr_complex, gr.sizeof_float, gr.sizeof_int, gr.sizeof_short, 14 | gr.sizeof_char] 15 | hide: part 16 | - id: num_inputs 17 | label: Num Inputs 18 | dtype: int 19 | default: '2' 20 | hide: part 21 | - id: num_outputs 22 | label: Num Outputs 23 | dtype: int 24 | default: '2' 25 | hide: part 26 | - id: input_index 27 | label: Input Index 28 | dtype: int 29 | default: '0' 30 | - id: output_index 31 | label: Output Index 32 | dtype: int 33 | default: '0' 34 | - id: vlen 35 | label: Vec Length 36 | dtype: int 37 | default: '1' 38 | hide: ${ 'part' if vlen == 1 else 'none' } 39 | 40 | inputs: 41 | - domain: stream 42 | dtype: ${ type } 43 | vlen: ${ vlen } 44 | multiplicity: ${ num_inputs } 45 | 46 | outputs: 47 | - domain: stream 48 | dtype: ${ type } 49 | vlen: ${ vlen } 50 | multiplicity: ${ num_outputs } 51 | asserts: 52 | - ${ vlen > 0 } 53 | 54 | templates: 55 | imports: import foo 56 | make: "foo.selector(\n\titem_size=${type.size}*${vlen},\n\tnum_inputs=${num_inputs},\n\ 57 | \tnum_outputs=${num_outputs},\n\tinput_index=${input_index},\n\toutput_index=${output_index},\n\ 58 | )" 59 | callbacks: 60 | - set_input_index(int(${input_index})) 61 | - set_output_index(int(${output_index})) 62 | 63 | documentation: |- 64 | Connect the sink at input index to the source at output index. Leave all other ports disconnected. 65 | 66 | file_format: 1 67 | -------------------------------------------------------------------------------- /grc/foo_valve.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_valve 4 | label: Valve 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [complex, float, int, short, byte] 12 | option_attributes: 13 | size: [gr.sizeof_gr_complex, gr.sizeof_float, gr.sizeof_int, gr.sizeof_short, 14 | gr.sizeof_char] 15 | hide: part 16 | - id: open 17 | label: Open 18 | dtype: raw 19 | default: '0' 20 | - id: vlen 21 | label: Vec Length 22 | dtype: int 23 | default: '1' 24 | hide: ${ 'part' if vlen == 1 else 'none' } 25 | 26 | inputs: 27 | - domain: stream 28 | dtype: ${ type } 29 | vlen: ${ vlen } 30 | 31 | outputs: 32 | - domain: stream 33 | dtype: ${ type } 34 | vlen: ${ vlen } 35 | asserts: 36 | - ${ vlen > 0 } 37 | 38 | templates: 39 | imports: import foo 40 | make: foo.valve(item_size=${type.size}*${vlen}, open=bool(${open})) 41 | callbacks: 42 | - set_open(bool(${open})) 43 | 44 | documentation: |- 45 | Connect output to input when valve is closed (not open). 46 | 47 | file_format: 1 48 | -------------------------------------------------------------------------------- /grc/foo_wireshark_connector.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: foo_wireshark_connector 4 | label: Wireshark Connector 5 | category: '[Foo]' 6 | 7 | parameters: 8 | - id: tech 9 | label: Technology 10 | dtype: enum 11 | default: '127' 12 | options: ['127', '195', '283'] 13 | option_labels: [WiFi, ZigBee, ZigBeeTap] 14 | - id: debug 15 | label: Debug 16 | dtype: bool 17 | default: 'False' 18 | options: ['True', 'False'] 19 | option_labels: [Enable, Disable] 20 | 21 | inputs: 22 | - domain: message 23 | id: in 24 | 25 | outputs: 26 | - domain: stream 27 | dtype: byte 28 | multiplicity: '1' 29 | 30 | templates: 31 | imports: import foo 32 | make: foo.wireshark_connector(${tech}, ${debug}) 33 | 34 | file_format: 1 35 | -------------------------------------------------------------------------------- /include/foo/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-foo 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 | burst_tagger.h 15 | channel_model.h 16 | packet_dropper.h 17 | packet_pad2.h 18 | periodic_msg_source.h 19 | random_periodic_msg_source.h 20 | rtt_measure.h 21 | wireshark_connector.h 22 | pad_tagged_stream.h 23 | DESTINATION include/foo 24 | ) 25 | -------------------------------------------------------------------------------- /include/foo/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-foo 6 | * 7 | * SPDX-License-Identifier: GPL-3.0-or-later 8 | * 9 | */ 10 | 11 | #ifndef INCLUDED_FOO_API_H 12 | #define INCLUDED_FOO_API_H 13 | 14 | #include 15 | 16 | #ifdef gnuradio_foo_EXPORTS 17 | #define FOO_API __GR_ATTR_EXPORT 18 | #else 19 | #define FOO_API __GR_ATTR_IMPORT 20 | #endif 21 | 22 | #endif /* INCLUDED_FOO_API_H */ 23 | -------------------------------------------------------------------------------- /include/foo/burst_tagger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Bastian Bloessl. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3, or (at your option) 7 | * any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this software; see the file COPYING. If not, write to 16 | * the Free Software Foundation, Inc., 51 Franklin Street, 17 | * Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | 21 | #ifndef INCLUDED_FOO_BURST_TAGGER_H 22 | #define INCLUDED_FOO_BURST_TAGGER_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace foo { 29 | 30 | class FOO_API burst_tagger : virtual public gr::sync_block { 31 | public: 32 | typedef std::shared_ptr sptr; 33 | 34 | static sptr make(pmt::pmt_t tag_name, unsigned int mult); 35 | }; 36 | 37 | } // namespace foo 38 | } // namespace gr 39 | 40 | #endif /* INCLUDED_FOO_BURST_TAGGER_H */ 41 | 42 | -------------------------------------------------------------------------------- /include/foo/channel_model.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_CHANNEL_MODEL_H 18 | #define INCLUDED_FOO_CHANNEL_MODEL_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace gr { 25 | namespace foo { 26 | 27 | class FOO_API channel_model : virtual public hier_block2 28 | { 29 | public: 30 | typedef std::shared_ptr sptr; 31 | 32 | static sptr make(double noise_voltage = 0.0, double frequency_offset = 0.0, 33 | double epsilon = 1.0, 34 | const std::vector &taps = std::vector(1, 1), 35 | double noise_seed = 0, bool block_tags = false); 36 | 37 | virtual void set_noise_voltage(double noise_voltage) = 0; 38 | virtual void set_frequency_offset(double frequency_offset) = 0; 39 | virtual void set_taps(const std::vector &taps) = 0; 40 | virtual void set_timing_offset(double epsilon) = 0; 41 | 42 | virtual double noise_voltage() const = 0; 43 | virtual double frequency_offset() const = 0; 44 | virtual std::vector taps() const = 0; 45 | virtual double timing_offset() const = 0; 46 | }; 47 | 48 | } // namespace foo 49 | } // namespace gr 50 | 51 | #endif /* INCLUDED_FOO_CHANNEL_MODEL_H */ 52 | -------------------------------------------------------------------------------- /include/foo/packet_dropper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Christoph Leitner 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_PACKET_DROPPER_H 18 | #define INCLUDED_FOO_PACKET_DROPPER_H 19 | 20 | #include 21 | #include 22 | 23 | namespace gr { 24 | namespace foo { 25 | 26 | class FOO_API packet_dropper : virtual public gr::block 27 | { 28 | public: 29 | typedef std::shared_ptr sptr; 30 | static sptr make(double drop_rate, unsigned long seed); 31 | }; 32 | } // namespace foo 33 | } // namespace gr 34 | 35 | #endif /* INCLUDED_FOO_PACKET_DROPPER_H */ 36 | -------------------------------------------------------------------------------- /include/foo/packet_pad2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_PACKET_PAD2_H 18 | #define INCLUDED_FOO_PACKET_PAD2_H 19 | 20 | #include 21 | #include 22 | 23 | namespace gr { 24 | namespace foo { 25 | 26 | class FOO_API packet_pad2 : virtual public gr::tagged_stream_block 27 | { 28 | public: 29 | 30 | typedef std::shared_ptr sptr; 31 | static sptr make(bool debug = false, bool delay=false, double delay_sec=0.01, unsigned int pad_front = 0, unsigned int pad_tail = 0); 32 | 33 | }; 34 | 35 | } // namespace foo 36 | } // namespace gr 37 | 38 | #endif /* INCLUDED_FOO_PACKET_PAD2_H */ 39 | -------------------------------------------------------------------------------- /include/foo/pad_tagged_stream.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 "Cyancali". 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_FOO_PAD_TAGGED_STREAM_H 22 | #define INCLUDED_FOO_PAD_TAGGED_STREAM_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace foo { 29 | 30 | /*! 31 | * \brief <+description of block+> 32 | * \ingroup foo 33 | * 34 | */ 35 | class FOO_API pad_tagged_stream : virtual public gr::tagged_stream_block 36 | { 37 | public: 38 | typedef std::shared_ptr sptr; 39 | 40 | /*! 41 | * \brief Return a shared_ptr to a new instance of foo::pad_tagged_stream. 42 | * 43 | * To avoid accidental use of raw pointers, foo::pad_tagged_stream's 44 | * constructor is in a private implementation 45 | * class. foo::pad_tagged_stream::make is the public interface for 46 | * creating new instances. 47 | */ 48 | static sptr make(int buffer_size, const std::string len_tag_name); 49 | }; 50 | 51 | } // namespace foo 52 | } // namespace gr 53 | 54 | #endif /* INCLUDED_FOO_PAD_TAGGED_STREAM_H */ 55 | 56 | -------------------------------------------------------------------------------- /include/foo/periodic_msg_source.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_PERIODIC_MSG_SOURCE_H 18 | #define INCLUDED_FOO_PERIODIC_MSG_SOURCE_H 19 | 20 | #include 21 | #include 22 | 23 | namespace gr { 24 | namespace foo { 25 | 26 | class FOO_API periodic_msg_source : virtual public gr::block 27 | { 28 | public: 29 | 30 | typedef std::shared_ptr sptr; 31 | static sptr make(pmt::pmt_t msg, long interval, int num_msg = -1, 32 | bool quit = true, bool debug = false); 33 | 34 | virtual void set_nmsg(int nmsg) = 0; 35 | virtual int get_nmsg() = 0; 36 | 37 | virtual void set_delay(long delay) = 0; 38 | virtual long get_delay() = 0; 39 | 40 | virtual void start_tx() = 0; 41 | virtual void stop_tx() = 0; 42 | virtual bool is_running() = 0; 43 | }; 44 | 45 | } // namespace foo 46 | } // namespace gr 47 | 48 | #endif /* INCLUDED_FOO_PERIODIC_MSG_SOURCE */ 49 | -------------------------------------------------------------------------------- /include/foo/random_periodic_msg_source.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2016 Bastian Bloessl 3 | * 2016 Paul Garver 4 | * 5 | * This program 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 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program 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 program. If not, see . 17 | */ 18 | #ifndef INCLUDED_FOO_RANDOM_PERIODIC_MSG_SOURCE_H 19 | #define INCLUDED_FOO_RANDOM_PERIODIC_MSG_SOURCE_H 20 | 21 | #include 22 | #include 23 | 24 | namespace gr { 25 | namespace foo { 26 | 27 | class FOO_API random_periodic_msg_source : virtual public gr::block 28 | { 29 | public: 30 | 31 | typedef std::shared_ptr sptr; 32 | static sptr make(int msg_len, long interval, int num_msg = 1, 33 | bool quit = true, bool debug = false, int seed = 0); 34 | 35 | virtual void set_nmsg(int nmsg) = 0; 36 | virtual int get_nmsg() = 0; 37 | 38 | virtual void set_delay(long delay) = 0; 39 | virtual long get_delay() = 0; 40 | 41 | virtual void start_tx() = 0; 42 | virtual void stop_tx() = 0; 43 | virtual bool is_running() = 0; 44 | }; 45 | 46 | } // namespace foo 47 | } // namespace gr 48 | 49 | #endif /* INCLUDED_FOO_RANDOM_PERIODIC_MSG_SOURCE */ 50 | -------------------------------------------------------------------------------- /include/foo/rtt_measure.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Christoph Leitner 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef INCLUDED_FOO_RTT_MEASURE_H 19 | #define INCLUDED_FOO_RTT_MEASURE_H 20 | 21 | #include 22 | #include 23 | 24 | namespace gr { 25 | namespace foo { 26 | 27 | class FOO_API rtt_measure : virtual public gr::block 28 | { 29 | public: 30 | typedef std::shared_ptr sptr; 31 | static sptr make(unsigned long interval); 32 | }; 33 | } // namespace foo 34 | } // namespace gr 35 | 36 | 37 | 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /include/foo/wireshark_connector.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_WIRESHARK_CONNECTOR_H 18 | #define INCLUDED_FOO_WIRESHARK_CONNECTOR_H 19 | 20 | #include 21 | #include 22 | 23 | namespace gr { 24 | namespace foo { 25 | 26 | enum LinkType { 27 | WIFI = 127, 28 | ZIGBEE = 195, 29 | ZIGBEE_TAP = 283 30 | }; 31 | 32 | class FOO_API wireshark_connector : virtual public gr::block 33 | { 34 | public: 35 | 36 | typedef std::shared_ptr sptr; 37 | static sptr make(LinkType type, bool debug= false); 38 | }; 39 | 40 | } // namespace foo 41 | } // namespace gr 42 | 43 | #endif /* INCLUDED_FOO_WIRESHARK_CONNECTOR_H */ 44 | -------------------------------------------------------------------------------- /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-foo 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 | include_directories( 15 | ${UHD_INCLUDE_DIRS} 16 | ) 17 | link_directories( 18 | ${UHD_LIBRARY_DIRS} 19 | ) 20 | 21 | list(APPEND foo_sources 22 | burst_tagger_impl.cc 23 | channel_model_impl.cc 24 | packet_dropper_impl.cc 25 | packet_pad2.cc 26 | periodic_msg_source_impl.cc 27 | random_periodic_msg_source_impl.cc 28 | rtt_measure_impl.cc 29 | wireshark_connector_impl.cc 30 | pad_tagged_stream_impl.cc 31 | ) 32 | 33 | set(foo_sources "${foo_sources}" PARENT_SCOPE) 34 | if(NOT foo_sources) 35 | MESSAGE(STATUS "No C++ sources... skipping lib/") 36 | return() 37 | endif(NOT foo_sources) 38 | 39 | add_library(gnuradio-foo SHARED ${foo_sources}) 40 | target_link_libraries(gnuradio-foo 41 | gnuradio::gnuradio-runtime 42 | gnuradio::gnuradio-pmt 43 | gnuradio::gnuradio-blocks 44 | gnuradio::gnuradio-filter 45 | gnuradio::gnuradio-analog 46 | ${UHD_LIBRARIES}) 47 | target_include_directories(gnuradio-foo 48 | PUBLIC $ 49 | PUBLIC $ 50 | ) 51 | set_target_properties(gnuradio-foo PROPERTIES DEFINE_SYMBOL "gnuradio_foo_EXPORTS") 52 | 53 | if(APPLE) 54 | set_target_properties(gnuradio-foo PROPERTIES 55 | INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" 56 | ) 57 | endif(APPLE) 58 | 59 | ######################################################################## 60 | # Install built library files 61 | ######################################################################## 62 | include(GrMiscUtils) 63 | GR_LIBRARY_FOO(gnuradio-foo) 64 | 65 | ######################################################################## 66 | # Print summary 67 | ######################################################################## 68 | message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") 69 | message(STATUS "Building for version: ${VERSION} / ${LIBVER}") 70 | 71 | ######################################################################## 72 | # Build and register unit test 73 | ######################################################################## 74 | include(GrTest) 75 | 76 | # If your unit tests require special include paths, add them here 77 | #include_directories() 78 | # List all files that contain Boost.UTF unit tests here 79 | list(APPEND test_foo_sources 80 | ) 81 | -------------------------------------------------------------------------------- /lib/burst_tagger_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Bastian Bloessl. 3 | * 4 | * This is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 3, or (at your option) 7 | * any later version. 8 | * 9 | * This software is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this software; see the file COPYING. If not, write to 16 | * the Free Software Foundation, Inc., 51 Franklin Street, 17 | * Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "burst_tagger_impl.h" 21 | 22 | #include 23 | #include 24 | 25 | namespace gr { 26 | namespace foo { 27 | 28 | burst_tagger_impl::burst_tagger_impl(pmt::pmt_t tag_name, 29 | unsigned int mult) 30 | : gr::sync_block("burst_tagger", 31 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 32 | gr::io_signature::make(1, 1, sizeof(gr_complex))), 33 | d_tag_name(tag_name), 34 | d_copy(0), 35 | d_mult(mult) { 36 | 37 | if(!d_mult) { 38 | throw std::out_of_range("multiplier must be > 0"); 39 | } 40 | } 41 | 42 | burst_tagger_impl::~burst_tagger_impl() { 43 | } 44 | 45 | void 46 | burst_tagger_impl::add_sob(uint64_t item) { 47 | static const pmt::pmt_t sob_key = pmt::string_to_symbol("tx_sob"); 48 | static const pmt::pmt_t value = pmt::PMT_T; 49 | static const pmt::pmt_t srcid = pmt::string_to_symbol(alias()); 50 | add_item_tag(0, item, sob_key, value, srcid); 51 | } 52 | 53 | 54 | void 55 | burst_tagger_impl::add_eob(uint64_t item) { 56 | static const pmt::pmt_t eob_key = pmt::string_to_symbol("tx_eob"); 57 | static const pmt::pmt_t value = pmt::PMT_T; 58 | static const pmt::pmt_t srcid = pmt::string_to_symbol(alias()); 59 | add_item_tag(0, item, eob_key, value, srcid); 60 | } 61 | 62 | 63 | int 64 | burst_tagger_impl::work(int noutput_items, 65 | gr_vector_const_void_star &input_items, 66 | gr_vector_void_star &output_items) { 67 | 68 | const gr_complex *in = (const gr_complex*)input_items[0]; 69 | gr_complex *out = (gr_complex*)output_items[0]; 70 | 71 | 72 | if(!d_copy) { 73 | std::vector tags; 74 | const uint64_t nread = nitems_read(0); 75 | 76 | get_tags_in_range(tags, 0, nread, nread + noutput_items, d_tag_name); 77 | std::sort(tags.begin(), tags.end(), tag_t::offset_compare); 78 | 79 | // copy until the first tag 80 | if(tags.size()) { 81 | tag_t tag = tags.front(); 82 | if(tag.offset == nitems_read(0)) { 83 | d_copy = pmt::to_uint64(tag.value) * d_mult; 84 | add_sob(nitems_written(0)); 85 | } else { 86 | uint64_t cpy = std::min((uint64_t)noutput_items, tag.offset - nitems_written(0)); 87 | std::memcpy(out, in, cpy * sizeof(gr_complex)); 88 | return cpy; 89 | } 90 | } 91 | } 92 | 93 | if(d_copy) { 94 | int cpy = std::min(d_copy, noutput_items); 95 | std::memcpy(out, in, cpy * sizeof(gr_complex)); 96 | d_copy -= cpy; 97 | if(d_copy == 0) { 98 | add_eob(nitems_written(0) + cpy - 1); 99 | } 100 | return cpy; 101 | } else { 102 | std::memcpy(out, in, noutput_items * sizeof(gr_complex)); 103 | return noutput_items; 104 | } 105 | } 106 | 107 | burst_tagger::sptr burst_tagger::make(pmt::pmt_t tag_name, unsigned int mult) { 108 | return gnuradio::get_initial_sptr(new burst_tagger_impl(tag_name, mult)); 109 | } 110 | 111 | 112 | } /* namespace foo */ 113 | } /* namespace gr */ 114 | 115 | -------------------------------------------------------------------------------- /lib/burst_tagger_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2013 Bastian Bloessl . 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_FOO_BURST_TAGGER_IMPL_H 22 | #define INCLUDED_FOO_BURST_TAGGER_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace foo { 28 | 29 | class burst_tagger_impl : public burst_tagger { 30 | private: 31 | void add_eob(uint64_t item); 32 | void add_sob(uint64_t item); 33 | 34 | pmt::pmt_t d_tag_name; 35 | int d_copy; 36 | unsigned int d_mult; 37 | 38 | public: 39 | burst_tagger_impl(pmt::pmt_t tag_name, 40 | unsigned int mult); 41 | ~burst_tagger_impl(); 42 | 43 | int work(int noutput_items, 44 | gr_vector_const_void_star &input_items, 45 | gr_vector_void_star &output_items); 46 | }; 47 | 48 | } // namespace foo 49 | } // namespace gr 50 | 51 | #endif /* INCLUDED_FOO_BURST_TAGGER_IMPL_H */ 52 | 53 | -------------------------------------------------------------------------------- /lib/channel_model_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "channel_model_impl.h" 19 | #include 20 | #include 21 | 22 | namespace gr { 23 | namespace foo { 24 | 25 | channel_model::sptr 26 | channel_model::make(double noise_voltage, 27 | double frequency_offset, 28 | double epsilon, 29 | const std::vector &taps, 30 | double noise_seed, 31 | bool block_tags) 32 | { 33 | return gnuradio::get_initial_sptr 34 | (new channel_model_impl(noise_voltage, 35 | frequency_offset, 36 | epsilon, 37 | taps, 38 | noise_seed, 39 | block_tags)); 40 | } 41 | 42 | // Hierarchical block constructor 43 | channel_model_impl::channel_model_impl(double noise_voltage, 44 | double frequency_offset, 45 | double epsilon, 46 | const std::vector &taps, 47 | double noise_seed, 48 | bool block_tags 49 | ) 50 | : hier_block2("channel_model", 51 | io_signature::make(1, 1, sizeof(gr_complex)), 52 | io_signature::make(1, 1, sizeof(gr_complex))) 53 | { 54 | d_taps = taps; 55 | while(d_taps.size() < 2) { 56 | d_taps.push_back(0); 57 | } 58 | 59 | d_timing_offset = filter::mmse_resampler_cc::make(0, epsilon); 60 | 61 | d_multipath = filter::fir_filter_ccc::make(1, d_taps); 62 | 63 | d_noise_adder = blocks::add_cc::make(); 64 | d_noise = analog::noise_source_c::make(analog::GR_GAUSSIAN, 65 | noise_voltage, noise_seed); 66 | d_freq_offset = analog::sig_source_c::make(1, analog::GR_SIN_WAVE, 67 | frequency_offset, 1.0, 0.0); 68 | d_mixer_offset = blocks::multiply_cc::make(); 69 | 70 | connect(self(), 0, d_timing_offset, 0); 71 | connect(d_timing_offset, 0, d_multipath, 0); 72 | connect(d_multipath, 0, d_mixer_offset, 0); 73 | connect(d_freq_offset, 0, d_mixer_offset, 1); 74 | connect(d_mixer_offset, 0, d_noise_adder, 1); 75 | connect(d_noise, 0, d_noise_adder, 0); 76 | connect(d_noise_adder, 0, self(), 0); 77 | 78 | if (block_tags) { 79 | d_timing_offset->set_tag_propagation_policy(gr::block::TPP_DONT); 80 | } 81 | } 82 | 83 | channel_model_impl::~channel_model_impl() 84 | { 85 | } 86 | 87 | void 88 | channel_model_impl::set_noise_voltage(double noise_voltage) 89 | { 90 | d_noise->set_amplitude(noise_voltage); 91 | } 92 | 93 | void 94 | channel_model_impl::set_frequency_offset(double frequency_offset) 95 | { 96 | d_freq_offset->set_frequency(frequency_offset); 97 | } 98 | 99 | void 100 | channel_model_impl::set_taps(const std::vector &taps) 101 | { 102 | d_taps = taps; 103 | while(d_taps.size() < 2) { 104 | d_taps.push_back(0); 105 | } 106 | d_multipath->set_taps(d_taps); 107 | } 108 | 109 | void 110 | channel_model_impl::set_timing_offset(double epsilon) 111 | { 112 | d_timing_offset->set_resamp_ratio(epsilon); 113 | } 114 | 115 | double 116 | channel_model_impl::noise_voltage() const 117 | { 118 | return d_noise->amplitude(); 119 | } 120 | 121 | double 122 | channel_model_impl::frequency_offset() const 123 | { 124 | return d_freq_offset->frequency(); 125 | } 126 | 127 | std::vector 128 | channel_model_impl::taps() const 129 | { 130 | return d_multipath->taps(); 131 | } 132 | 133 | double 134 | channel_model_impl::timing_offset() const 135 | { 136 | return d_timing_offset->resamp_ratio(); 137 | } 138 | 139 | } /* namespace channels */ 140 | } /* namespace gr */ 141 | -------------------------------------------------------------------------------- /lib/channel_model_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_CHANNEL_MODEL_IMPL_H 18 | #define INCLUDED_FOO_CHANNEL_MODEL_IMPL_H 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace gr { 31 | namespace foo { 32 | 33 | class FOO_API channel_model_impl : public foo::channel_model 34 | { 35 | private: 36 | blocks::add_cc::sptr d_noise_adder; 37 | blocks::multiply_cc::sptr d_mixer_offset; 38 | 39 | analog::sig_source_c::sptr d_freq_offset; 40 | analog::noise_source_c::sptr d_noise; 41 | 42 | filter::mmse_resampler_cc::sptr d_timing_offset; 43 | filter::fir_filter_ccc::sptr d_multipath; 44 | 45 | std::vector d_taps; 46 | 47 | public: 48 | channel_model_impl(double noise_voltage, 49 | double frequency_offset, 50 | double epsilon, 51 | const std::vector &taps, 52 | double noise_seed, 53 | bool block_tags); 54 | 55 | ~channel_model_impl(); 56 | 57 | void set_noise_voltage(double noise_voltage); 58 | void set_frequency_offset(double frequency_offset); 59 | void set_taps(const std::vector &taps); 60 | void set_timing_offset(double epsilon); 61 | 62 | double noise_voltage() const; 63 | double frequency_offset() const; 64 | std::vector taps() const; 65 | double timing_offset() const; 66 | }; 67 | 68 | } // namespace foo 69 | } // namespace gr 70 | 71 | #endif /* INCLUDED_FOO_CHANNEL_MODEL_IMPL_H */ 72 | -------------------------------------------------------------------------------- /lib/packet_dropper_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Christoph Leitner 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "packet_dropper_impl.h" 19 | #include 20 | 21 | using namespace gr::foo; 22 | 23 | packet_dropper_impl::packet_dropper_impl(double drop_rate, unsigned long seed) 24 | : block("packet_dropper", 25 | gr::io_signature::make(0, 0, 0), 26 | gr::io_signature::make(0, 0, 0)), 27 | d_drop_rate(drop_rate), 28 | d_generator(seed), 29 | d_distribution(0.0, 1.0) 30 | { 31 | if(d_drop_rate >= 1){ 32 | throw std::out_of_range("drop rate has to be < 1"); 33 | } 34 | message_port_register_in(pmt::mp("in")); 35 | set_msg_handler(pmt::mp("in"), boost::bind(&packet_dropper_impl::msg_handler, this, boost::placeholders::_1)); 36 | message_port_register_out(pmt::mp("out")); 37 | } 38 | 39 | void 40 | packet_dropper_impl::msg_handler(pmt::pmt_t msg) 41 | { 42 | if(d_distribution(d_generator) <= d_drop_rate){ 43 | return; 44 | } 45 | message_port_pub(pmt::mp("out"), msg); 46 | } 47 | 48 | packet_dropper::sptr 49 | packet_dropper::make(double drop_rate, unsigned long seed) 50 | { 51 | return gnuradio::get_initial_sptr(new packet_dropper_impl(drop_rate, seed)); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /lib/packet_dropper_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Christoph Leitner 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef INCLUDED_FOO_PACKET_DROPPER_IMPL_H 19 | #define INCLUDED_FOO_PACKET_DROPPER_IMPL_H 20 | 21 | #include 22 | #include 23 | 24 | namespace gr { 25 | namespace foo { 26 | class packet_dropper_impl : public packet_dropper { 27 | private: 28 | double d_drop_rate; 29 | std::default_random_engine d_generator; 30 | std::uniform_real_distribution d_distribution; 31 | void msg_handler(pmt::pmt_t msg); 32 | public: 33 | packet_dropper_impl(double drop_rate, unsigned long seed); 34 | }; 35 | } 36 | } 37 | 38 | #endif /* INCLUDED_FOO_PACKET_DROPPER_IMPL_H */ 39 | -------------------------------------------------------------------------------- /lib/packet_pad2.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include 18 | 19 | #include 20 | #include 21 | #ifdef FOO_UHD 22 | #include 23 | #endif 24 | 25 | using namespace gr::foo; 26 | 27 | 28 | class packet_pad2_impl : public packet_pad2 { 29 | 30 | public: 31 | packet_pad2_impl(bool debug, bool delay, double delay_sec, unsigned int pad_front, unsigned int pad_tail) : tagged_stream_block("foo_packet_pad2", 32 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 33 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 34 | "packet_len"), 35 | d_debug(debug), 36 | d_delay(delay), 37 | d_delay_sec(delay_sec), 38 | d_pad_front(pad_front), 39 | d_pad_tail(pad_tail) { 40 | set_tag_propagation_policy(block::TPP_DONT); 41 | } 42 | 43 | ~packet_pad2_impl(){ 44 | } 45 | 46 | int calculate_output_stream_length(const gr_vector_int &ninput_items) { 47 | return ninput_items[0] + d_pad_front + d_pad_tail; 48 | } 49 | 50 | int work (int noutput_items, gr_vector_int& ninput_items, 51 | gr_vector_const_void_star& input_items, 52 | gr_vector_void_star& output_items) { 53 | 54 | const gr_complex *in = (const gr_complex*)input_items[0]; 55 | gr_complex *out = (gr_complex*)output_items[0]; 56 | 57 | std::memset(out, 0x00, sizeof(gr_complex) * (ninput_items[0] + d_pad_front + d_pad_tail)); 58 | 59 | std::memcpy(out + d_pad_front, in, sizeof(gr_complex) * ninput_items[0]); 60 | 61 | 62 | int produced = ninput_items[0] + d_pad_front + d_pad_tail; 63 | const pmt::pmt_t src = pmt::string_to_symbol(alias()); 64 | 65 | #ifdef FOO_UHD 66 | if(d_delay) { 67 | static const pmt::pmt_t time_key = pmt::string_to_symbol("tx_time"); 68 | double t_now( 69 | std::chrono::duration(std::chrono::system_clock::now() 70 | .time_since_epoch() 71 | ).count() 72 | ); 73 | uhd::time_spec_t now = uhd::time_spec_t(t_now) 74 | + uhd::time_spec_t(d_delay_sec); 75 | 76 | const pmt::pmt_t time_value = pmt::make_tuple( 77 | pmt::from_uint64(now.get_full_secs()), 78 | pmt::from_double(now.get_frac_secs()) 79 | ); 80 | add_item_tag(0, nitems_written(0), time_key, time_value, src); 81 | } 82 | #endif 83 | 84 | std::vector tags; 85 | get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + ninput_items[0]); 86 | for (size_t i = 0; i < tags.size(); i++) { 87 | add_item_tag(0, nitems_written(0), 88 | tags[i].key, 89 | tags[i].value); 90 | } 91 | 92 | return produced; 93 | } 94 | 95 | private: 96 | bool d_debug; 97 | bool d_delay; 98 | double d_delay_sec; 99 | unsigned int d_pad_front; 100 | unsigned int d_pad_tail; 101 | }; 102 | 103 | packet_pad2::sptr 104 | packet_pad2::make(bool debug, bool delay, double delay_sec, unsigned int pad_front, unsigned int pad_tail) { 105 | return gnuradio::get_initial_sptr(new packet_pad2_impl(debug, delay, delay_sec, pad_front, pad_tail)); 106 | } 107 | -------------------------------------------------------------------------------- /lib/pad_tagged_stream_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 "Cyancali". 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 "config.h" 23 | #endif 24 | 25 | #include 26 | #include "pad_tagged_stream_impl.h" 27 | 28 | namespace gr { 29 | namespace foo { 30 | 31 | pad_tagged_stream::sptr 32 | pad_tagged_stream::make(int buffer_size, const std::string len_tag_name) 33 | { 34 | return gnuradio::get_initial_sptr 35 | (new pad_tagged_stream_impl(buffer_size, len_tag_name)); 36 | } 37 | 38 | 39 | /* 40 | * The private constructor 41 | */ 42 | pad_tagged_stream_impl::pad_tagged_stream_impl(int buffer_size, const std::string len_tag_name) 43 | : gr::tagged_stream_block("pad_tagged_stream", 44 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 45 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 46 | len_tag_name), 47 | d_buf_len(buffer_size), 48 | d_len_tag(len_tag_name) 49 | { 50 | set_min_output_buffer(buffer_size*2); 51 | set_tag_propagation_policy(TPP_DONT); 52 | } 53 | 54 | /* 55 | * Our virtual destructor. 56 | */ 57 | pad_tagged_stream_impl::~pad_tagged_stream_impl() 58 | { 59 | } 60 | 61 | int 62 | pad_tagged_stream_impl::calculate_output_stream_length(const gr_vector_int &ninput_items) 63 | { 64 | return d_buf_len; 65 | } 66 | 67 | int 68 | pad_tagged_stream_impl::work (int noutput_items, 69 | gr_vector_int &ninput_items, 70 | gr_vector_const_void_star &input_items, 71 | gr_vector_void_star &output_items) 72 | { 73 | const gr_complex *in = (const gr_complex *) input_items[0]; 74 | gr_complex *out = (gr_complex *) output_items[0]; 75 | 76 | noutput_items = d_buf_len; 77 | 78 | 79 | memcpy(out, in, sizeof(gr_complex) * std::min(d_buf_len, ninput_items[0])); 80 | 81 | if (ninput_items[0] <= noutput_items) 82 | { 83 | memset((out+ninput_items[0]), 0, sizeof(gr_complex) * noutput_items-ninput_items[0]); 84 | } 85 | else // ninput_items[0] > noutput_items 86 | { 87 | std::cout << "PadTaggedStream: Warning - Tagged stream is longer than buffer" << std::endl; 88 | } 89 | 90 | return noutput_items; 91 | } 92 | 93 | } /* namespace foo */ 94 | } /* namespace gr */ 95 | 96 | -------------------------------------------------------------------------------- /lib/pad_tagged_stream_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 "Cyancali". 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_FOO_PAD_TAGGED_STREAM_IMPL_H 22 | #define INCLUDED_FOO_PAD_TAGGED_STREAM_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace foo { 28 | 29 | class pad_tagged_stream_impl : public pad_tagged_stream 30 | { 31 | private: 32 | int d_buf_len; 33 | std::string d_len_tag; 34 | 35 | public: 36 | pad_tagged_stream_impl(int buffer_size, const std::string len_tag_name); 37 | ~pad_tagged_stream_impl(); 38 | 39 | int calculate_output_stream_length(const gr_vector_int &ninput_items); 40 | 41 | // Where all the action really happens 42 | int work(int noutput_items, 43 | gr_vector_int &ninput_items, 44 | gr_vector_const_void_star &input_items, 45 | gr_vector_void_star &output_items); 46 | }; 47 | 48 | } // namespace foo 49 | } // namespace gr 50 | 51 | #endif /* INCLUDED_FOO_PAD_TAGGED_STREAM_IMPL_H */ 52 | 53 | -------------------------------------------------------------------------------- /lib/periodic_msg_source_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "periodic_msg_source_impl.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace gr::foo; 24 | 25 | #define dout d_debug && std::cout 26 | 27 | periodic_msg_source_impl::periodic_msg_source_impl(pmt::pmt_t msg, 28 | long interval, int num_msg, bool quit, bool debug) : 29 | block("periodic_msg_source", 30 | gr::io_signature::make(0, 0, 0), 31 | gr::io_signature::make(0, 0, 0)), 32 | d_msg(msg), 33 | d_nmsg_total(num_msg), 34 | d_nmsg_left(num_msg), 35 | d_interval(interval), 36 | d_debug(debug), 37 | d_finished(false), 38 | d_quit(quit) { 39 | 40 | message_port_register_out(pmt::mp("out")); 41 | 42 | d_thread = new boost::thread(boost::bind(&periodic_msg_source_impl::run, this, this)); 43 | } 44 | 45 | periodic_msg_source_impl::~periodic_msg_source_impl() { 46 | gr::thread::scoped_lock d_mutex; 47 | 48 | d_finished = true; 49 | d_thread->interrupt(); 50 | d_thread->join(); 51 | delete d_thread; 52 | } 53 | 54 | void 55 | periodic_msg_source_impl::run(periodic_msg_source_impl *instance) { 56 | 57 | // flow graph startup delay 58 | boost::this_thread::sleep(boost::posix_time::milliseconds(500)); 59 | 60 | while(1) { 61 | long delay; 62 | { 63 | gr::thread::scoped_lock d_mutex; 64 | if(d_finished || !d_nmsg_left) { 65 | d_finished = true; 66 | if(d_quit) { 67 | boost::this_thread::sleep(boost::posix_time::milliseconds(500)); 68 | post(pmt::mp("system"), pmt::cons(pmt::mp("done"), pmt::from_long(1))); 69 | } 70 | break; 71 | } 72 | 73 | dout << "PMS: number of messages left: " << d_nmsg_left << std::endl; 74 | 75 | message_port_pub( pmt::mp("out"), d_msg ); 76 | 77 | if(d_nmsg_left > 0) { 78 | d_nmsg_left--; 79 | } 80 | 81 | delay = d_interval; 82 | } 83 | boost::this_thread::sleep(boost::posix_time::milliseconds(delay)); 84 | } 85 | } 86 | 87 | void 88 | periodic_msg_source_impl::set_nmsg(int nmsg) { 89 | gr::thread::scoped_lock d_mutex; 90 | d_nmsg_total = nmsg; 91 | } 92 | 93 | int 94 | periodic_msg_source_impl::get_nmsg() { 95 | gr::thread::scoped_lock d_mutex; 96 | return d_nmsg_total; 97 | } 98 | 99 | void 100 | periodic_msg_source_impl::set_delay(long delay) { 101 | gr::thread::scoped_lock d_mutex; 102 | d_interval = delay; 103 | } 104 | 105 | long 106 | periodic_msg_source_impl::get_delay() { 107 | gr::thread::scoped_lock d_mutex; 108 | return d_interval; 109 | } 110 | 111 | 112 | void 113 | periodic_msg_source_impl::start_tx() { 114 | gr::thread::scoped_lock d_mutex; 115 | 116 | if(is_running()) return; 117 | 118 | d_nmsg_left = d_nmsg_total; 119 | d_finished = false; 120 | d_thread->join(); 121 | delete d_thread; 122 | 123 | d_thread = new boost::thread(boost::bind(&periodic_msg_source_impl::run, this, this)); 124 | } 125 | 126 | void 127 | periodic_msg_source_impl::stop_tx() { 128 | d_thread->interrupt(); 129 | } 130 | 131 | bool 132 | periodic_msg_source_impl::is_running() { 133 | return !d_finished; 134 | } 135 | 136 | periodic_msg_source::sptr 137 | periodic_msg_source::make(pmt::pmt_t msg, long interval, int num_msg, bool quit, bool debug) { 138 | return gnuradio::get_initial_sptr(new periodic_msg_source_impl(msg, interval, num_msg, quit, debug)); 139 | } 140 | -------------------------------------------------------------------------------- /lib/periodic_msg_source_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_PERIODIC_MSG_SOURCE_IMPL_H 18 | #define INCLUDED_FOO_PERIODIC_MSG_SOURCE_IMPL_H 19 | 20 | #include 21 | 22 | namespace gr { 23 | namespace foo { 24 | 25 | class periodic_msg_source_impl : public periodic_msg_source { 26 | private: 27 | void run(periodic_msg_source_impl *instance); 28 | 29 | int d_nmsg_total; 30 | int d_nmsg_left; 31 | bool d_debug; 32 | bool d_quit; 33 | bool d_finished; 34 | long d_interval; 35 | pmt::pmt_t d_msg; 36 | boost::thread *d_thread; 37 | gr::thread::mutex d_mutex; 38 | 39 | public: 40 | periodic_msg_source_impl(pmt::pmt_t msg, 41 | long interval, int num_msg, 42 | bool quit, bool debug); 43 | virtual ~periodic_msg_source_impl(); 44 | 45 | void set_nmsg(int nmsg); 46 | int get_nmsg(); 47 | 48 | void set_delay(long delay); 49 | long get_delay(); 50 | 51 | void start_tx(); 52 | void stop_tx(); 53 | bool is_running(); 54 | 55 | }; 56 | 57 | } // namespace foo 58 | } // namespace gr 59 | 60 | #endif /* INCLUDED_FOO_PERIODIC_MSG_SOURCE_IMPL_H */ 61 | -------------------------------------------------------------------------------- /lib/random_periodic_msg_source_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * Copyright (C) 2016 Paul Garver 4 | * 5 | * This program 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 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program 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 program. If not, see . 17 | */ 18 | // Just like periodic_msg_source but random data for every message 19 | #include "random_periodic_msg_source_impl.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace gr::foo; 26 | 27 | #define dout d_debug && std::cout 28 | 29 | random_periodic_msg_source_impl::random_periodic_msg_source_impl(int msg_len, 30 | long interval, int num_msg, bool quit, bool debug, int seed): 31 | block("random_periodic_msg_source", 32 | gr::io_signature::make(0, 0, 0), 33 | gr::io_signature::make(0, 0, 0)), 34 | d_msg_len(msg_len), 35 | d_nmsg_total(num_msg), 36 | d_nmsg_left(num_msg), 37 | d_interval(interval), 38 | d_debug(debug), 39 | d_finished(false), 40 | d_quit(quit), 41 | d_seed(static_cast(seed)), 42 | d_brange(0,255), 43 | d_rng(seed), 44 | d_randbytes(d_rng,d_brange) 45 | { 46 | message_port_register_out(pmt::mp("out")); 47 | 48 | d_thread = new boost::thread(boost::bind(&random_periodic_msg_source_impl::run, this, this)); 49 | } 50 | 51 | random_periodic_msg_source_impl::~random_periodic_msg_source_impl() { 52 | gr::thread::scoped_lock d_mutex; 53 | d_finished = true; 54 | d_thread->interrupt(); 55 | d_thread->join(); 56 | delete d_thread; 57 | } 58 | 59 | void 60 | random_periodic_msg_source_impl::run(random_periodic_msg_source_impl *instance) { 61 | 62 | // flow graph startup delay 63 | boost::this_thread::sleep(boost::posix_time::milliseconds(500)); 64 | 65 | while(1) { 66 | long delay; 67 | { 68 | gr::thread::scoped_lock d_mutex; 69 | if(d_finished || !d_nmsg_left) { 70 | d_finished = true; 71 | if(d_quit) { 72 | boost::this_thread::sleep(boost::posix_time::milliseconds(500)); 73 | post(pmt::mp("system"), pmt::cons(pmt::mp("done"), pmt::from_long(1))); 74 | } 75 | break; 76 | } 77 | 78 | dout << "PMS: number of messages left: " << d_nmsg_left << std::endl; 79 | // Generate a random message 80 | pmt::pmt_t msg = generate_msg(); 81 | message_port_pub( pmt::mp("out"), msg); 82 | 83 | if(d_nmsg_left > 0) { 84 | d_nmsg_left--; 85 | } 86 | 87 | delay = d_interval; 88 | } 89 | boost::this_thread::sleep(boost::posix_time::milliseconds(delay)); 90 | } 91 | } 92 | 93 | // Generate a random message 94 | pmt::pmt_t 95 | random_periodic_msg_source_impl::generate_msg() { 96 | std::vector vec(d_msg_len); 97 | 98 | for(int i = 0; i < d_msg_len; i++) { 99 | vec[i] = d_randbytes(); 100 | } 101 | 102 | pmt::pmt_t blob = pmt::make_blob(vec.data(), d_msg_len); 103 | return pmt::cons(pmt::PMT_NIL, blob); 104 | } 105 | void 106 | random_periodic_msg_source_impl::set_nmsg(int nmsg) { 107 | gr::thread::scoped_lock d_mutex; 108 | d_nmsg_total = nmsg; 109 | } 110 | 111 | int 112 | random_periodic_msg_source_impl::get_nmsg() { 113 | gr::thread::scoped_lock d_mutex; 114 | return d_nmsg_total; 115 | } 116 | 117 | void 118 | random_periodic_msg_source_impl::set_delay(long delay) { 119 | gr::thread::scoped_lock d_mutex; 120 | d_interval = delay; 121 | } 122 | 123 | long 124 | random_periodic_msg_source_impl::get_delay() { 125 | gr::thread::scoped_lock d_mutex; 126 | return d_interval; 127 | } 128 | 129 | 130 | void 131 | random_periodic_msg_source_impl::start_tx() { 132 | gr::thread::scoped_lock d_mutex; 133 | 134 | if(is_running()) return; 135 | 136 | d_nmsg_left = d_nmsg_total; 137 | d_finished = false; 138 | d_thread->join(); 139 | delete d_thread; 140 | 141 | d_thread = new boost::thread(boost::bind(&random_periodic_msg_source_impl::run, this, this)); 142 | } 143 | 144 | void 145 | random_periodic_msg_source_impl::stop_tx() { 146 | d_thread->interrupt(); 147 | } 148 | 149 | bool 150 | random_periodic_msg_source_impl::is_running() { 151 | return !d_finished; 152 | } 153 | 154 | random_periodic_msg_source::sptr 155 | random_periodic_msg_source::make(int msg_len, long interval, int num_msg, 156 | bool quit, bool debug,int seed) { 157 | return gnuradio::get_initial_sptr(new random_periodic_msg_source_impl(msg_len, interval, num_msg, quit, debug, seed)); 158 | } 159 | -------------------------------------------------------------------------------- /lib/random_periodic_msg_source_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * Copyright (C) 2016 Paul Garver 4 | * 5 | * This program 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 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program 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 program. If not, see . 17 | */ 18 | #ifndef INCLUDED_FOO_RANDOM_PERIODIC_MSG_SOURCE_IMPL_H 19 | #define INCLUDED_FOO_RANDOM_PERIODIC_MSG_SOURCE_IMPL_H 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace gr { 26 | namespace foo { 27 | 28 | class random_periodic_msg_source_impl : public random_periodic_msg_source { 29 | private: 30 | void run(random_periodic_msg_source_impl *instance); 31 | int d_msg_len; 32 | int d_nmsg_total; 33 | int d_nmsg_left; 34 | unsigned int d_seed; 35 | bool d_debug; 36 | bool d_quit; 37 | bool d_finished; 38 | long d_interval; 39 | boost::thread *d_thread; 40 | gr::thread::mutex d_mutex; 41 | boost::mt19937 d_rng; 42 | boost::uniform_int<> d_brange; 43 | boost::variate_generator< boost::mt19937, boost::uniform_int<> > d_randbytes; 44 | 45 | public: 46 | random_periodic_msg_source_impl(int msg_len, 47 | long interval, int num_msg, 48 | bool quit, bool debug, int seed); 49 | virtual ~random_periodic_msg_source_impl(); 50 | 51 | void set_nmsg(int nmsg); 52 | int get_nmsg(); 53 | 54 | void set_delay(long delay); 55 | long get_delay(); 56 | 57 | void start_tx(); 58 | void stop_tx(); 59 | pmt::pmt_t generate_msg(); 60 | bool is_running(); 61 | 62 | }; 63 | 64 | } // namespace foo 65 | } // namespace gr 66 | 67 | #endif /* INCLUDED_FOO_RANDOM_PERIODIC_MSG_SOURCE_IMPL_H */ 68 | -------------------------------------------------------------------------------- /lib/rtt_measure_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Christoph Leitner 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "rtt_measure_impl.h" 19 | #include 20 | 21 | using namespace gr::foo; 22 | 23 | rtt_measure_impl::rtt_measure_impl(unsigned long interval) 24 | : block("rtt_measure", 25 | gr::io_signature::make(0, 0, 0), 26 | gr::io_signature::make(1, 1, sizeof(uint8_t))), 27 | d_interval(interval), d_thread(&rtt_measure_impl::run, this), 28 | d_stop(false) 29 | { 30 | message_port_register_in(pmt::mp("in")); 31 | message_port_register_out(pmt::mp("out")); 32 | } 33 | 34 | rtt_measure_impl::~rtt_measure_impl() { 35 | d_stop.store(true); 36 | d_thread.interrupt(); //if thread was sleeping 37 | d_thread.join(); 38 | } 39 | 40 | void 41 | rtt_measure_impl::run() 42 | { 43 | // flow graph startup delay 44 | boost::this_thread::sleep(boost::posix_time::milliseconds(500)); 45 | std::string text("fnord"); 46 | pmt::pmt_t msg = pmt::make_blob(text.data(), text.length()); 47 | while(!d_stop.load()){ 48 | gr::thread::scoped_lock lock(d_mutex); 49 | message_port_pub(pmt::mp("out"), pmt::cons(pmt::PMT_NIL, msg)); 50 | d_start_time = boost::posix_time::microsec_clock::local_time(); 51 | lock.unlock(); 52 | boost::this_thread::sleep(boost::posix_time::milliseconds(d_interval)); 53 | } 54 | } 55 | 56 | int 57 | rtt_measure_impl::general_work(int noutput, gr_vector_int& ninput_items, 58 | gr_vector_const_void_star& input_items, 59 | gr_vector_void_star& output_items ) 60 | { 61 | gr_complex *out = (gr_complex*)output_items[0]; 62 | 63 | pmt::pmt_t msg(delete_head_nowait(pmt::mp("in"))); 64 | if(!msg.get()){ 65 | return 0; 66 | } 67 | boost::posix_time::time_duration dur = 68 | boost::posix_time::microsec_clock::local_time() - start_time(); 69 | std::string time_string(std::to_string(dur.total_microseconds()) + "\n"); 70 | std::cout << time_string; 71 | 72 | if(pmt::is_eof_object(msg)) { 73 | return -1; 74 | } else if(!pmt::is_pair(msg)) { 75 | throw std::invalid_argument("only PDU messages allowed"); 76 | } 77 | int to_copy = time_string.length(); 78 | std::memcpy(out, time_string.data(), to_copy); 79 | 80 | return to_copy; 81 | } 82 | 83 | boost::posix_time::ptime 84 | rtt_measure_impl::start_time() 85 | { 86 | gr::thread::scoped_lock d_mutex; 87 | return d_start_time; 88 | } 89 | 90 | rtt_measure::sptr 91 | rtt_measure::make(unsigned long interval) 92 | { 93 | return gnuradio::get_initial_sptr(new rtt_measure_impl(interval)); 94 | } 95 | -------------------------------------------------------------------------------- /lib/rtt_measure_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Christoph Leitner 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #ifndef INCLUDED_FOO_RTT_MEASURE_IMPL_H 19 | #define INCLUDED_FOO_RTT_MEASURE_IMPL_H 20 | 21 | #include 22 | #include 23 | namespace gr { 24 | namespace foo { 25 | class rtt_measure_impl : public rtt_measure { 26 | private: 27 | unsigned long d_interval; 28 | std::atomic_bool d_stop; 29 | boost::posix_time::ptime d_start_time; 30 | gr::thread::mutex d_mutex; 31 | gr::thread::thread d_thread; 32 | gr::thread::condition_variable d_msg_received; 33 | public: 34 | rtt_measure_impl(unsigned long interval); 35 | ~rtt_measure_impl(); 36 | void run(); 37 | int general_work(int noutput, gr_vector_int& ninput_items, 38 | gr_vector_const_void_star& input_items, 39 | gr_vector_void_star& output_items ); 40 | boost::posix_time::ptime start_time(); 41 | }; 42 | } 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /lib/wireshark_connector_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "wireshark_connector_impl.h" 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | using namespace gr::foo; 28 | 29 | 30 | #define dout d_debug && std::cout 31 | 32 | wireshark_connector_impl::wireshark_connector_impl(LinkType type, bool debug) : 33 | block ("wireshark_connector", 34 | gr::io_signature::make(0, 0, 0), 35 | gr::io_signature::make(1, 1, sizeof(uint8_t))), 36 | d_msg_offset(0), 37 | d_debug(debug), 38 | d_link(type) { 39 | 40 | message_port_register_in(pmt::mp("in")); 41 | 42 | d_msg_len = sizeof(pcap_file_hdr); 43 | d_msg = reinterpret_cast(std::malloc(d_msg_len)); 44 | 45 | pcap_file_hdr *hdr = reinterpret_cast(d_msg); 46 | hdr->magic_number = 0xa1b2c3d4; 47 | hdr->version_major = 2; 48 | hdr->version_minor = 4; 49 | hdr->thiszone = 0; 50 | hdr->sigfigs = 0; 51 | hdr->snaplen = 65535; 52 | hdr->network = d_link; 53 | } 54 | 55 | void 56 | wireshark_connector_impl::handle_pdu(pmt::pmt_t pdu) { 57 | 58 | // get current time 59 | auto tp_now = std::chrono::system_clock::now(); 60 | auto tp_now_sec = std::chrono::floor(tp_now); 61 | auto duration_us = std::chrono::duration_cast( 62 | tp_now - tp_now_sec 63 | ); 64 | auto ts_sec = tp_now_sec.time_since_epoch().count(); 65 | auto ts_usec = duration_us.count(); 66 | 67 | const char *buf = reinterpret_cast(pmt::blob_data(pmt::cdr(pdu))); 68 | std::size_t len = pmt::blob_length(pmt::cdr(pdu)); 69 | std::size_t offset = 0; 70 | 71 | switch(d_link) { 72 | 73 | case WIFI: { 74 | 75 | // if crc is included ignore last 4 bytes 76 | pmt::pmt_t dict = pmt::car(pdu); 77 | pmt::pmt_t crc_inc = pmt::dict_ref(dict, pmt::mp("crc_included"), pmt::PMT_NIL); 78 | if(pmt::is_bool(crc_inc) && pmt::is_true(crc_inc)) { 79 | len -= 4; 80 | } 81 | 82 | // pcap header 83 | d_msg = reinterpret_cast(std::malloc( 84 | len + sizeof(radiotap_hdr) + sizeof(pcap_hdr))); 85 | 86 | pcap_hdr *hdr = reinterpret_cast(d_msg); 87 | hdr->ts_sec = ts_sec; 88 | hdr->ts_usec = ts_usec; 89 | hdr->incl_len = len + sizeof(radiotap_hdr); 90 | hdr->orig_len = len + sizeof(radiotap_hdr); 91 | offset += sizeof(struct pcap_hdr); 92 | 93 | // check if rate is attached 94 | uint8_t rate = 12; 95 | pmt::pmt_t encoding = pmt::dict_ref(dict, pmt::mp("encoding"), pmt::PMT_NIL); 96 | if(pmt::is_uint64(encoding)) { 97 | rate = encoding_to_rate(pmt::to_uint64(encoding)); 98 | } 99 | 100 | int snr = 42; 101 | if(pmt::dict_has_key(dict, pmt::mp("snr"))) { 102 | pmt::pmt_t s = pmt::dict_ref(dict, pmt::mp("snr"), pmt::PMT_NIL); 103 | if(pmt::is_number(s)) { 104 | snr = std::round(pmt::to_double(s)); 105 | } 106 | } 107 | 108 | uint8_t signal = 0; 109 | uint8_t noise = 0; 110 | 111 | if(snr >= 0) { 112 | signal = snr; 113 | noise = 0; 114 | } else { 115 | signal = 0; 116 | noise = -1 * snr; 117 | } 118 | 119 | // radiotap header 120 | radiotap_hdr *rhdr = reinterpret_cast(d_msg + offset); 121 | rhdr->version = 0; 122 | rhdr->hdr_length = sizeof(radiotap_hdr); 123 | rhdr->bitmap = 0x0000086e; 124 | rhdr->flags = 0; 125 | rhdr->rate = rate; 126 | rhdr->channel = 178; 127 | rhdr->signal = signal; 128 | rhdr->noise = noise; 129 | rhdr->antenna = 1; 130 | offset += sizeof(struct radiotap_hdr); 131 | 132 | break; 133 | } 134 | 135 | case ZIGBEE: { 136 | 137 | d_msg = reinterpret_cast(std::malloc( 138 | len + sizeof(pcap_hdr))); 139 | 140 | pcap_hdr *hdr = reinterpret_cast(d_msg); 141 | hdr->ts_sec = ts_sec; 142 | hdr->ts_usec = ts_usec; 143 | hdr->incl_len = len; 144 | hdr->orig_len = len; 145 | offset += sizeof(pcap_hdr); 146 | break; 147 | } 148 | 149 | case ZIGBEE_TAP:{ 150 | 151 | const size_t max_extra_size = sizeof(tap_hdr) + sizeof(tap_tlv_fcs) + sizeof(tap_tlv_channel) + sizeof(tap_tlv_lqi); 152 | size_t extra_size = sizeof(tap_hdr) + sizeof(tap_tlv_fcs); 153 | d_msg = reinterpret_cast(std::malloc(len + sizeof(pcap_hdr) + max_extra_size)); 154 | 155 | 156 | pcap_hdr *hdr = reinterpret_cast(d_msg); 157 | hdr->ts_sec = ts_sec; 158 | hdr->ts_usec = ts_usec; 159 | // hdr->incl_len is set at the end of the scope 160 | // hdr->orig_len is set at the end of the scope 161 | offset += sizeof(pcap_hdr); 162 | 163 | tap_hdr *tap = reinterpret_cast(d_msg + offset); 164 | tap->version = 0; 165 | tap->reserved = 0; 166 | // tap->length is set at the end of the scope 167 | offset += sizeof(tap_hdr); 168 | 169 | tap_tlv_fcs *fcs = reinterpret_cast(d_msg + offset); 170 | fcs->type = 0; // FCS_TYPE 171 | fcs->length = 1; 172 | fcs->fcs_type = 1; // 16 bit crc 173 | for (int i = 0; i < 3; i++) { 174 | fcs->padding[i] = 0; 175 | } 176 | offset += sizeof(tap_tlv_fcs); 177 | 178 | pmt::pmt_t dict = pmt::car(pdu); 179 | if(pmt::dict_has_key(dict, pmt::mp("channel"))) { 180 | pmt::pmt_t s = pmt::dict_ref(dict, pmt::mp("channel"), pmt::PMT_NIL); 181 | if(pmt::is_integer(s)) { 182 | tap_tlv_channel *chan = reinterpret_cast(d_msg + offset); 183 | chan->type = 3; // CHANNEL_ASSIGNMENT 184 | chan->length = 3; 185 | chan->channel_number = (uint16_t)pmt::to_long(s); 186 | chan->channel_page = 0; 187 | chan->padding = 0; 188 | offset += sizeof(tap_tlv_channel); 189 | extra_size += sizeof(tap_tlv_channel); 190 | } 191 | } 192 | 193 | if(pmt::dict_has_key(dict, pmt::mp("lqi"))) { 194 | pmt::pmt_t s = pmt::dict_ref(dict, pmt::mp("lqi"), pmt::PMT_NIL); 195 | if(pmt::is_integer(s)) { 196 | tap_tlv_lqi *lqi = reinterpret_cast(d_msg + offset); 197 | lqi->type = 10; // LQI 198 | lqi->length = 1; 199 | lqi->lqi = (uint8_t)pmt::to_long(s); 200 | for (int i = 0; i < 3; i++) { 201 | lqi->padding[i] = 0; 202 | } 203 | offset += sizeof(tap_tlv_lqi); 204 | extra_size += sizeof(tap_tlv_lqi); 205 | } 206 | } 207 | 208 | tap->length = extra_size; 209 | hdr->incl_len = len + extra_size; 210 | hdr->orig_len = len + extra_size; 211 | break; 212 | } 213 | 214 | } 215 | 216 | memcpy(d_msg + offset, buf, len); 217 | d_msg_len = offset + len; 218 | } 219 | 220 | uint8_t 221 | wireshark_connector_impl::encoding_to_rate(uint64_t encoding) { 222 | 223 | // rates in radiotab rate field 224 | // are in 0.5 Mbit/s steps 225 | switch(encoding) { 226 | case 0: 227 | return 6 * 2; 228 | case 1: 229 | return 9 * 2; 230 | case 2: 231 | return 12 * 2; 232 | case 3: 233 | return 18 * 2; 234 | case 4: 235 | return 24 * 2; 236 | case 5: 237 | return 36 * 2; 238 | case 6: 239 | return 48 * 2; 240 | case 7: 241 | return 54 * 2; 242 | } 243 | 244 | throw std::invalid_argument("wrong encoding"); 245 | return 0; 246 | } 247 | 248 | int 249 | wireshark_connector_impl::general_work(int noutput, gr_vector_int& ninput_items, 250 | gr_vector_const_void_star& input_items, 251 | gr_vector_void_star& output_items ) { 252 | 253 | gr_complex *out = (gr_complex*)output_items[0]; 254 | 255 | if(!d_msg_len) { 256 | pmt::pmt_t msg(delete_head_nowait(pmt::mp("in"))); 257 | 258 | if(!msg) { 259 | return 0; 260 | } 261 | 262 | if(pmt::is_eof_object(msg)) { 263 | dout << "WIRESHARK: exiting" << std::endl; 264 | return -1; 265 | } else if(pmt::is_pair(msg)) { 266 | dout << "WIRESHARK: received new message" << std::endl; 267 | dout << "message length " << pmt::blob_length(pmt::cdr(msg)) << std::endl; 268 | handle_pdu(msg); 269 | } else { 270 | dout << "WIRESHARK: ignoring message" << std::endl; 271 | return 0; 272 | } 273 | } 274 | 275 | int to_copy = std::min((d_msg_len - d_msg_offset), noutput); 276 | memcpy(out, d_msg + d_msg_offset, to_copy); 277 | 278 | dout << "WIRESHARK: d_msg_offset: " << d_msg_offset << 279 | " to_copy: " << to_copy << 280 | " d_msg_len " << d_msg_len << std::endl; 281 | 282 | d_msg_offset += to_copy; 283 | 284 | if(d_msg_offset == d_msg_len) { 285 | d_msg_offset = 0; 286 | d_msg_len = 0; 287 | std::free(d_msg); 288 | } 289 | 290 | dout << "WIRESHARK: output size: " << noutput << 291 | " produced items: " << to_copy << std::endl; 292 | return to_copy; 293 | } 294 | 295 | wireshark_connector::sptr 296 | wireshark_connector::make(LinkType type, bool debug) { 297 | return gnuradio::get_initial_sptr(new wireshark_connector_impl(type, debug)); 298 | } 299 | -------------------------------------------------------------------------------- /lib/wireshark_connector_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Bastian Bloessl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef INCLUDED_FOO_WIRESHARK_CONNECTOR_IMPL_H 18 | #define INCLUDED_FOO_WIRESHARK_CONNECTOR_IMPL_H 19 | 20 | #include 21 | #include 22 | 23 | namespace gr { 24 | namespace foo { 25 | 26 | class wireshark_connector_impl : public wireshark_connector { 27 | private: 28 | uint8_t encoding_to_rate(uint64_t encoding); 29 | void handle_pdu(pmt::pmt_t pdu); 30 | 31 | bool d_debug; 32 | int d_msg_offset; 33 | int d_msg_len; 34 | char* d_msg; 35 | LinkType d_link; 36 | public: 37 | wireshark_connector_impl(LinkType type, bool debug); 38 | int general_work(int noutput, gr_vector_int& ninput_items, 39 | gr_vector_const_void_star& input_items, 40 | gr_vector_void_star& output_items ); 41 | }; 42 | 43 | #pragma pack(push, 1) 44 | struct pcap_file_hdr { 45 | uint32_t magic_number; /* magic number */ 46 | uint16_t version_major; /* major version number */ 47 | uint16_t version_minor; /* minor version number */ 48 | int32_t thiszone; /* GMT to local correction */ 49 | uint32_t sigfigs; /* accuracy of timestamps */ 50 | uint32_t snaplen; /* max length of captured packets, in octets */ 51 | uint32_t network; /* data link type */ 52 | }; 53 | #pragma pack(pop) 54 | 55 | #pragma pack(push, 1) 56 | struct pcap_hdr { 57 | uint32_t ts_sec; /* timestamp seconds */ 58 | uint32_t ts_usec; /* timestamp microseconds */ 59 | uint32_t incl_len; /* number of octets of packet saved in file */ 60 | uint32_t orig_len; /* actual length of packet */ 61 | }; 62 | #pragma pack(pop) 63 | 64 | #pragma pack(push, 1) 65 | struct radiotap_hdr { 66 | uint16_t version; 67 | uint16_t hdr_length; 68 | uint32_t bitmap; 69 | uint8_t flags; 70 | uint8_t rate; 71 | uint32_t channel; 72 | uint8_t signal; 73 | uint8_t noise; 74 | uint8_t antenna; 75 | }; 76 | #pragma pack(pop) 77 | 78 | #pragma pack(push, 1) 79 | // An 802.15.4 TAP header as defined in https://gitlab.com/exegin/ieee802-15-4-tap/ 80 | struct tap_hdr { 81 | uint8_t version; 82 | uint8_t reserved; 83 | uint16_t length; 84 | }; 85 | #pragma pack(pop) 86 | 87 | 88 | #pragma pack(push, 1) 89 | struct tap_tlv_fcs { 90 | uint16_t type; // FCS_TYPE = 0 91 | uint16_t length; // 1 92 | uint8_t fcs_type; // 0 = None, 1 = 16-bit CRC, 2 = 32-bit CRC 93 | uint8_t padding[3]; // Should be 0 padded 94 | }; 95 | #pragma pack(pop) 96 | 97 | #pragma pack(push, 1) 98 | struct tap_tlv_channel { 99 | uint16_t type; // CHANNEL_ASSIGNMENT = 3 100 | uint16_t length; // 3 101 | uint16_t channel_number; 102 | uint8_t channel_page; 103 | uint8_t padding; // Should be 0 padded 104 | }; 105 | #pragma pack(pop) 106 | 107 | #pragma pack(push, 1) 108 | struct tap_tlv_lqi { 109 | uint16_t type; // LQI_TYPE = 10 110 | uint16_t length; // 1 111 | uint8_t lqi; 112 | uint8_t padding[3]; // Should be 0 padded 113 | }; 114 | #pragma pack(pop) 115 | 116 | } // namespace foo 117 | } // namespace gr 118 | 119 | #endif /* INCLUDED_FOO_WIRESHARK_CONNECTOR_IMPL_H */ 120 | -------------------------------------------------------------------------------- /python/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-foo 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 | selector.py 26 | DESTINATION ${GR_PYTHON_DIR}/foo 27 | ) 28 | 29 | ######################################################################## 30 | # Handle the unit tests 31 | ######################################################################## 32 | include(GrTest) 33 | 34 | set(GR_TEST_TARGET_DEPS gnuradio-foo) 35 | -------------------------------------------------------------------------------- /python/__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 FOO module. Place your Python package 11 | description here (python/__init__.py). 12 | ''' 13 | import os 14 | 15 | # import pybind11 generated symbols into the foo namespace 16 | try: 17 | # this might fail if the module is python-only 18 | from .foo_python import * 19 | except ModuleNotFoundError: 20 | pass 21 | 22 | # import any pure python here 23 | from .selector import * 24 | # 25 | -------------------------------------------------------------------------------- /python/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 foo_sources) 12 | MESSAGE(STATUS "No C++ sources... skipping python bindings") 13 | return() 14 | endif(NOT foo_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 foo_python_files 32 | python_bindings.cc 33 | 34 | burst_tagger_python.cc 35 | channel_model_python.cc 36 | packet_dropper_python.cc 37 | packet_pad2_python.cc 38 | pad_tagged_stream_python.cc 39 | periodic_msg_source_python.cc 40 | random_periodic_msg_source_python.cc 41 | rtt_measure_python.cc 42 | wireshark_connector_python.cc 43 | ) 44 | 45 | GR_PYBIND_MAKE_OOT(foo 46 | ../.. 47 | gr::foo 48 | "${foo_python_files}") 49 | 50 | install(TARGETS foo_python DESTINATION ${GR_PYTHON_DIR}/foo COMPONENT pythonapi) 51 | -------------------------------------------------------------------------------- /python/bindings/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bastibl/gr-foo/4c2a471b0453b9dca669b2d9dfcbfba6278741d7/python/bindings/README.md -------------------------------------------------------------------------------- /python/bindings/bind_oot_file.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import argparse 3 | import os 4 | from gnuradio.bindtool import BindingGenerator 5 | import pathlib 6 | import sys 7 | 8 | parser = argparse.ArgumentParser(description='Bind a GR Out of Tree Block') 9 | parser.add_argument('--module', type=str, 10 | help='Name of gr module containing file to bind (e.g. fft digital analog)') 11 | 12 | parser.add_argument('--output_dir', default='/tmp', 13 | help='Output directory of generated bindings') 14 | parser.add_argument('--prefix', help='Prefix of Installed GNU Radio') 15 | parser.add_argument('--src', help='Directory of gnuradio source tree', 16 | default=os.path.dirname(os.path.abspath(__file__))+'/../../..') 17 | 18 | parser.add_argument( 19 | '--filename', help="File to be parsed") 20 | 21 | parser.add_argument( 22 | '--defines', help='Set additional defines for precompiler',default=(), nargs='*') 23 | parser.add_argument( 24 | '--include', help='Additional Include Dirs, separated', default=(), nargs='*') 25 | 26 | parser.add_argument( 27 | '--status', help='Location of output file for general status (used during cmake)', default=None 28 | ) 29 | parser.add_argument( 30 | '--flag_automatic', default='0' 31 | ) 32 | parser.add_argument( 33 | '--flag_pygccxml', default='0' 34 | ) 35 | 36 | args = parser.parse_args() 37 | 38 | prefix = args.prefix 39 | output_dir = args.output_dir 40 | defines = tuple(','.join(args.defines).split(',')) 41 | includes = ','.join(args.include) 42 | name = args.module 43 | 44 | namespace = ['gr', name] 45 | prefix_include_root = name 46 | 47 | 48 | with warnings.catch_warnings(): 49 | warnings.filterwarnings("ignore", category=DeprecationWarning) 50 | 51 | bg = BindingGenerator(prefix, namespace, 52 | prefix_include_root, output_dir, define_symbols=defines, addl_includes=includes, 53 | catch_exceptions=False, write_json_output=False, status_output=args.status, 54 | flag_automatic=True if args.flag_automatic.lower() in [ 55 | '1', 'true'] else False, 56 | flag_pygccxml=True if args.flag_pygccxml.lower() in ['1', 'true'] else False) 57 | bg.gen_file_binding(args.filename) 58 | -------------------------------------------------------------------------------- /python/bindings/burst_tagger_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(burst_tagger.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(c99561501264e56677e8f0631b47434d) */ 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_burst_tagger(py::module& m) 31 | { 32 | 33 | using burst_tagger = ::gr::foo::burst_tagger; 34 | 35 | 36 | py::class_>(m, "burst_tagger", D(burst_tagger)) 38 | 39 | .def(py::init(&burst_tagger::make), 40 | py::arg("tag_name"), 41 | py::arg("mult"), 42 | D(burst_tagger,make) 43 | ) 44 | 45 | 46 | 47 | 48 | ; 49 | 50 | 51 | 52 | 53 | } 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /python/bindings/channel_model_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(channel_model.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(2d1fbde4f2f01f74496f71008f2acb85) */ 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_channel_model(py::module& m) 31 | { 32 | 33 | using channel_model = ::gr::foo::channel_model; 34 | 35 | 36 | py::class_>(m, "channel_model", D(channel_model)) 38 | 39 | .def(py::init(&channel_model::make), 40 | py::arg("noise_voltage") = 0., 41 | py::arg("frequency_offset") = 0., 42 | py::arg("epsilon") = 1., 43 | py::arg("taps") = std::vector(1, 1), 44 | py::arg("noise_seed") = 0, 45 | py::arg("block_tags") = false, 46 | D(channel_model,make) 47 | ) 48 | 49 | 50 | 51 | 52 | 53 | 54 | .def("set_noise_voltage",&channel_model::set_noise_voltage, 55 | py::arg("noise_voltage"), 56 | D(channel_model,set_noise_voltage) 57 | ) 58 | 59 | 60 | 61 | .def("set_frequency_offset",&channel_model::set_frequency_offset, 62 | py::arg("frequency_offset"), 63 | D(channel_model,set_frequency_offset) 64 | ) 65 | 66 | 67 | 68 | .def("set_taps",&channel_model::set_taps, 69 | py::arg("taps"), 70 | D(channel_model,set_taps) 71 | ) 72 | 73 | 74 | 75 | .def("set_timing_offset",&channel_model::set_timing_offset, 76 | py::arg("epsilon"), 77 | D(channel_model,set_timing_offset) 78 | ) 79 | 80 | 81 | 82 | .def("noise_voltage",&channel_model::noise_voltage, 83 | D(channel_model,noise_voltage) 84 | ) 85 | 86 | 87 | 88 | .def("frequency_offset",&channel_model::frequency_offset, 89 | D(channel_model,frequency_offset) 90 | ) 91 | 92 | 93 | 94 | .def("taps",&channel_model::taps, 95 | D(channel_model,taps) 96 | ) 97 | 98 | 99 | 100 | .def("timing_offset",&channel_model::timing_offset, 101 | D(channel_model,timing_offset) 102 | ) 103 | 104 | ; 105 | 106 | 107 | 108 | 109 | } 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /python/bindings/docstrings/README.md: -------------------------------------------------------------------------------- 1 | This directory stores templates for docstrings that are scraped from the include header files for each block -------------------------------------------------------------------------------- /python/bindings/docstrings/burst_tagger_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_burst_tagger = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_burst_tagger_burst_tagger = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_burst_tagger_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/channel_model_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_channel_model = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_channel_model_channel_model_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_channel_model_channel_model_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_foo_channel_model_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_foo_channel_model_set_noise_voltage = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_foo_channel_model_set_frequency_offset = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_foo_channel_model_set_taps = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_foo_channel_model_set_timing_offset = R"doc()doc"; 41 | 42 | 43 | static const char *__doc_gr_foo_channel_model_noise_voltage = R"doc()doc"; 44 | 45 | 46 | static const char *__doc_gr_foo_channel_model_frequency_offset = R"doc()doc"; 47 | 48 | 49 | static const char *__doc_gr_foo_channel_model_taps = R"doc()doc"; 50 | 51 | 52 | static const char *__doc_gr_foo_channel_model_timing_offset = R"doc()doc"; 53 | 54 | 55 | -------------------------------------------------------------------------------- /python/bindings/docstrings/packet_dropper_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_packet_dropper = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_packet_dropper_packet_dropper = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_packet_dropper_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/packet_pad2_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_packet_pad2 = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_packet_pad2_packet_pad2 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_packet_pad2_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/pad_tagged_stream_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_pad_tagged_stream = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_pad_tagged_stream_pad_tagged_stream = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_pad_tagged_stream_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/periodic_msg_source_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_periodic_msg_source = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_periodic_msg_source_periodic_msg_source_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_periodic_msg_source_periodic_msg_source_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_foo_periodic_msg_source_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_foo_periodic_msg_source_set_nmsg = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_foo_periodic_msg_source_get_nmsg = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_foo_periodic_msg_source_set_delay = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_foo_periodic_msg_source_get_delay = R"doc()doc"; 41 | 42 | 43 | static const char *__doc_gr_foo_periodic_msg_source_start_tx = R"doc()doc"; 44 | 45 | 46 | static const char *__doc_gr_foo_periodic_msg_source_stop_tx = R"doc()doc"; 47 | 48 | 49 | static const char *__doc_gr_foo_periodic_msg_source_is_running = R"doc()doc"; 50 | 51 | 52 | -------------------------------------------------------------------------------- /python/bindings/docstrings/random_periodic_msg_source_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_random_periodic_msg_source = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_random_periodic_msg_source_random_periodic_msg_source_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_random_periodic_msg_source_random_periodic_msg_source_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_foo_random_periodic_msg_source_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_foo_random_periodic_msg_source_set_nmsg = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_foo_random_periodic_msg_source_get_nmsg = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_foo_random_periodic_msg_source_set_delay = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_foo_random_periodic_msg_source_get_delay = R"doc()doc"; 41 | 42 | 43 | static const char *__doc_gr_foo_random_periodic_msg_source_start_tx = R"doc()doc"; 44 | 45 | 46 | static const char *__doc_gr_foo_random_periodic_msg_source_stop_tx = R"doc()doc"; 47 | 48 | 49 | static const char *__doc_gr_foo_random_periodic_msg_source_is_running = R"doc()doc"; 50 | 51 | 52 | -------------------------------------------------------------------------------- /python/bindings/docstrings/rtt_measure_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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,foo, __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_foo_rtt_measure = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_foo_rtt_measure_rtt_measure = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_foo_rtt_measure_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/wireshark_connector_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 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, foo, __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 | static const char* __doc_gr_foo_wireshark_connector = R"doc()doc"; 19 | 20 | 21 | static const char* __doc_gr_foo_wireshark_connector_wireshark_connector_0 = R"doc()doc"; 22 | 23 | 24 | static const char* __doc_gr_foo_wireshark_connector_make = R"doc()doc"; 25 | -------------------------------------------------------------------------------- /python/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 | 53 | def argParse(): 54 | """Parses commandline args.""" 55 | desc='Reads the parameters from the comment block in the pybind files' 56 | parser = ArgumentParser(description=desc) 57 | 58 | parser.add_argument("function", help="Operation to perform on comment block of pybind file", choices=["flag_auto","flag_pygccxml","header_filename","header_file_hash","all"]) 59 | parser.add_argument("pathname", help="Pathname of pybind c++ file to read, e.g. blockname_python.cc") 60 | 61 | return parser.parse_args() 62 | 63 | if __name__ == "__main__": 64 | # Parse command line options and set up doxyxml. 65 | args = argParse() 66 | 67 | pbhp = PybindHeaderParser(args.pathname) 68 | 69 | if args.function == "flag_auto": 70 | print(pbhp.get_flag_automatic()) 71 | elif args.function == "flag_pygccxml": 72 | print(pbhp.get_flag_pygccxml()) 73 | elif args.function == "header_filename": 74 | print(pbhp.get_header_filename()) 75 | elif args.function == "header_file_hash": 76 | print(pbhp.get_header_file_hash()) 77 | elif args.function == "all": 78 | print(pbhp.get_flags()) -------------------------------------------------------------------------------- /python/bindings/packet_dropper_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(packet_dropper.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(c324ec3cc59fd3973f47d4c8193587cb) */ 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_packet_dropper(py::module& m) 31 | { 32 | 33 | using packet_dropper = ::gr::foo::packet_dropper; 34 | 35 | 36 | py::class_>(m, "packet_dropper", D(packet_dropper)) 38 | 39 | .def(py::init(&packet_dropper::make), 40 | py::arg("drop_rate"), 41 | py::arg("seed"), 42 | D(packet_dropper,make) 43 | ) 44 | 45 | 46 | 47 | 48 | ; 49 | 50 | 51 | 52 | 53 | } 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /python/bindings/packet_pad2_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(packet_pad2.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(b2e434a4d5f7a750e8183bd819862469) */ 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_packet_pad2(py::module& m) 31 | { 32 | 33 | using packet_pad2 = ::gr::foo::packet_pad2; 34 | 35 | 36 | py::class_>(m, "packet_pad2", D(packet_pad2)) 38 | 39 | .def(py::init(&packet_pad2::make), 40 | py::arg("debug") = false, 41 | py::arg("delay") = false, 42 | py::arg("delay_sec") = 0.01, 43 | py::arg("pad_front") = 0, 44 | py::arg("pad_tail") = 0, 45 | D(packet_pad2,make) 46 | ) 47 | 48 | 49 | 50 | 51 | ; 52 | 53 | 54 | 55 | 56 | } 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /python/bindings/pad_tagged_stream_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(pad_tagged_stream.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(7a558a15cd1883b28237a8c9f3d5419f) */ 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_pad_tagged_stream(py::module& m) 31 | { 32 | 33 | using pad_tagged_stream = ::gr::foo::pad_tagged_stream; 34 | 35 | 36 | py::class_>(m, "pad_tagged_stream", D(pad_tagged_stream)) 38 | 39 | .def(py::init(&pad_tagged_stream::make), 40 | py::arg("buffer_size"), 41 | py::arg("len_tag_name"), 42 | D(pad_tagged_stream,make) 43 | ) 44 | 45 | 46 | 47 | 48 | ; 49 | 50 | 51 | 52 | 53 | } 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /python/bindings/periodic_msg_source_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(periodic_msg_source.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(3aa9b26f640e6e96cbfa5450af8f4ac7) */ 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_periodic_msg_source(py::module& m) 31 | { 32 | 33 | using periodic_msg_source = ::gr::foo::periodic_msg_source; 34 | 35 | 36 | py::class_>(m, "periodic_msg_source", D(periodic_msg_source)) 38 | 39 | .def(py::init(&periodic_msg_source::make), 40 | py::arg("msg"), 41 | py::arg("interval"), 42 | py::arg("num_msg") = -1, 43 | py::arg("quit") = true, 44 | py::arg("debug") = false, 45 | D(periodic_msg_source,make) 46 | ) 47 | 48 | 49 | 50 | 51 | 52 | 53 | .def("set_nmsg",&periodic_msg_source::set_nmsg, 54 | py::arg("nmsg"), 55 | D(periodic_msg_source,set_nmsg) 56 | ) 57 | 58 | 59 | 60 | .def("get_nmsg",&periodic_msg_source::get_nmsg, 61 | D(periodic_msg_source,get_nmsg) 62 | ) 63 | 64 | 65 | 66 | .def("set_delay",&periodic_msg_source::set_delay, 67 | py::arg("delay"), 68 | D(periodic_msg_source,set_delay) 69 | ) 70 | 71 | 72 | 73 | .def("get_delay",&periodic_msg_source::get_delay, 74 | D(periodic_msg_source,get_delay) 75 | ) 76 | 77 | 78 | 79 | .def("start_tx",&periodic_msg_source::start_tx, 80 | D(periodic_msg_source,start_tx) 81 | ) 82 | 83 | 84 | 85 | .def("stop_tx",&periodic_msg_source::stop_tx, 86 | D(periodic_msg_source,stop_tx) 87 | ) 88 | 89 | 90 | 91 | .def("is_running",&periodic_msg_source::is_running, 92 | D(periodic_msg_source,is_running) 93 | ) 94 | 95 | ; 96 | 97 | 98 | 99 | 100 | } 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /python/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 | 12 | #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION 13 | #include 14 | 15 | namespace py = pybind11; 16 | 17 | // Headers for binding functions 18 | /**************************************/ 19 | // The following comment block is used for 20 | // gr_modtool to insert function prototypes 21 | // Please do not delete 22 | /**************************************/ 23 | // BINDING_FUNCTION_PROTOTYPES( 24 | void bind_burst_tagger(py::module& m); 25 | void bind_channel_model(py::module& m); 26 | void bind_packet_dropper(py::module& m); 27 | void bind_packet_pad2(py::module& m); 28 | void bind_pad_tagged_stream(py::module& m); 29 | void bind_periodic_msg_source(py::module& m); 30 | void bind_random_periodic_msg_source(py::module& m); 31 | void bind_rtt_measure(py::module& m); 32 | void bind_wireshark_connector(py::module& m); 33 | // ) END BINDING_FUNCTION_PROTOTYPES 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 | 45 | PYBIND11_MODULE(foo_python, m) 46 | { 47 | // Initialize the numpy C API 48 | // (otherwise we will see segmentation faults) 49 | init_numpy(); 50 | 51 | // Allow access to base block methods 52 | py::module::import("gnuradio.gr"); 53 | 54 | /**************************************/ 55 | // The following comment block is used for 56 | // gr_modtool to insert binding function calls 57 | // Please do not delete 58 | /**************************************/ 59 | // BINDING_FUNCTION_CALLS( 60 | bind_burst_tagger(m); 61 | bind_channel_model(m); 62 | bind_packet_dropper(m); 63 | bind_packet_pad2(m); 64 | bind_pad_tagged_stream(m); 65 | bind_periodic_msg_source(m); 66 | bind_random_periodic_msg_source(m); 67 | bind_rtt_measure(m); 68 | bind_wireshark_connector(m); 69 | // ) END BINDING_FUNCTION_CALLS 70 | } 71 | -------------------------------------------------------------------------------- /python/bindings/random_periodic_msg_source_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(random_periodic_msg_source.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(0a96820144211e87383cb24fd175ffdf) */ 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_random_periodic_msg_source(py::module& m) 31 | { 32 | 33 | using random_periodic_msg_source = ::gr::foo::random_periodic_msg_source; 34 | 35 | 36 | py::class_>(m, "random_periodic_msg_source", D(random_periodic_msg_source)) 38 | 39 | .def(py::init(&random_periodic_msg_source::make), 40 | py::arg("msg_len"), 41 | py::arg("interval"), 42 | py::arg("num_msg") = 1, 43 | py::arg("quit") = true, 44 | py::arg("debug") = false, 45 | py::arg("seed") = 0, 46 | D(random_periodic_msg_source,make) 47 | ) 48 | 49 | 50 | 51 | 52 | 53 | 54 | .def("set_nmsg",&random_periodic_msg_source::set_nmsg, 55 | py::arg("nmsg"), 56 | D(random_periodic_msg_source,set_nmsg) 57 | ) 58 | 59 | 60 | 61 | .def("get_nmsg",&random_periodic_msg_source::get_nmsg, 62 | D(random_periodic_msg_source,get_nmsg) 63 | ) 64 | 65 | 66 | 67 | .def("set_delay",&random_periodic_msg_source::set_delay, 68 | py::arg("delay"), 69 | D(random_periodic_msg_source,set_delay) 70 | ) 71 | 72 | 73 | 74 | .def("get_delay",&random_periodic_msg_source::get_delay, 75 | D(random_periodic_msg_source,get_delay) 76 | ) 77 | 78 | 79 | 80 | .def("start_tx",&random_periodic_msg_source::start_tx, 81 | D(random_periodic_msg_source,start_tx) 82 | ) 83 | 84 | 85 | 86 | .def("stop_tx",&random_periodic_msg_source::stop_tx, 87 | D(random_periodic_msg_source,stop_tx) 88 | ) 89 | 90 | 91 | 92 | .def("is_running",&random_periodic_msg_source::is_running, 93 | D(random_periodic_msg_source,is_running) 94 | ) 95 | 96 | ; 97 | 98 | 99 | 100 | 101 | } 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /python/bindings/rtt_measure_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 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(rtt_measure.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(30ed3e91a71527c380abe7384d62fcea) */ 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_rtt_measure(py::module& m) 31 | { 32 | 33 | using rtt_measure = ::gr::foo::rtt_measure; 34 | 35 | 36 | py::class_>(m, "rtt_measure", D(rtt_measure)) 38 | 39 | .def(py::init(&rtt_measure::make), 40 | py::arg("interval"), 41 | D(rtt_measure,make) 42 | ) 43 | 44 | 45 | 46 | 47 | ; 48 | 49 | 50 | 51 | 52 | } 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /python/bindings/wireshark_connector_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 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(wireshark_connector.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(fcd645d2eb8f7772de5e8ded1ce89be8) */ 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_wireshark_connector(py::module& m) 31 | { 32 | 33 | using wireshark_connector = ::gr::foo::wireshark_connector; 34 | 35 | 36 | py::class_>( 40 | m, "wireshark_connector", D(wireshark_connector)) 41 | 42 | .def(py::init(&wireshark_connector::make), 43 | py::arg("type"), 44 | py::arg("debug") = false, 45 | D(wireshark_connector, make)) 46 | 47 | 48 | ; 49 | 50 | py::enum_<::gr::foo::LinkType>(m, "LinkType") 51 | .value("WIFI", ::gr::foo::LinkType::WIFI) // 127 52 | .value("ZIGBEE", ::gr::foo::LinkType::ZIGBEE) // 195 53 | .value("ZIGBEE_TAP", ::gr::foo::LinkType::ZIGBEE_TAP) // 283 54 | .export_values(); 55 | 56 | py::implicitly_convertible(); 57 | } 58 | -------------------------------------------------------------------------------- /python/selector.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017 Bastian Bloessl 3 | # 4 | # This is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 3, or (at your option) 7 | # any later version. 8 | # 9 | # This software is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this software; see the file COPYING. If not, write to 16 | # the Free Software Foundation, Inc., 51 Franklin Street, 17 | # Boston, MA 02110-1301, USA. 18 | 19 | from gnuradio import gr 20 | from gnuradio import blocks 21 | 22 | class selector(gr.hier_block2): 23 | """A hier2 block with N inputs and M outputs, where data is only forwarded through input n to output m.""" 24 | def __init__(self, item_size, num_inputs, num_outputs, input_index, output_index): 25 | """ 26 | Selector constructor. 27 | 28 | Args: 29 | item_size: the size of the gr data stream in bytes 30 | num_inputs: the number of inputs (integer) 31 | num_outputs: the number of outputs (integer) 32 | input_index: the index for the source data 33 | output_index: the index for the destination data 34 | """ 35 | gr.hier_block2.__init__( 36 | self, 'selector', 37 | gr.io_signature(num_inputs, num_inputs, item_size), 38 | gr.io_signature(num_outputs, num_outputs, item_size), 39 | ) 40 | 41 | #terminator blocks for unused inputs and outputs 42 | self.input_terminators = [blocks.null_sink(item_size) for i in range(num_inputs)] 43 | self.output_terminators = [blocks.head(item_size, 0) for i in range(num_outputs)] 44 | self.copy = blocks.copy(item_size) 45 | #connections 46 | for i in range(num_inputs): self.connect((self, i), self.input_terminators[i]) 47 | for i in range(num_outputs): self.connect(blocks.null_source(item_size), 48 | self.output_terminators[i], (self, i)) 49 | self.item_size = item_size 50 | self.input_index = input_index 51 | self.output_index = output_index 52 | self.num_inputs = num_inputs 53 | self.num_outputs = num_outputs 54 | self._connect_current() 55 | 56 | def _indexes_valid(self): 57 | """ 58 | Are the input and output indexes within range of the number of inputs and outputs? 59 | 60 | Returns: 61 | true if input index and output index are in range 62 | """ 63 | return self.input_index in range(self.num_inputs) and self.output_index in range(self.num_outputs) 64 | 65 | def _connect_current(self): 66 | """If the input and output indexes are valid: 67 | disconnect the blocks at the input and output index from their terminators, 68 | and connect them to one another. Then connect the terminators to one another.""" 69 | if self._indexes_valid(): 70 | self.disconnect((self, self.input_index), self.input_terminators[self.input_index]) 71 | self.disconnect(self.output_terminators[self.output_index], (self, self.output_index)) 72 | self.connect((self, self.input_index), self.copy) 73 | self.connect(self.copy, (self, self.output_index)) 74 | self.connect(self.output_terminators[self.output_index], self.input_terminators[self.input_index]) 75 | 76 | def _disconnect_current(self): 77 | """If the input and output indexes are valid: 78 | disconnect the blocks at the input and output index from one another, 79 | and the terminators at the input and output index from one another. 80 | Reconnect the blocks to the terminators.""" 81 | if self._indexes_valid(): 82 | self.disconnect((self, self.input_index), self.copy) 83 | self.disconnect(self.copy, (self, self.output_index)) 84 | self.disconnect(self.output_terminators[self.output_index], self.input_terminators[self.input_index]) 85 | self.connect((self, self.input_index), self.input_terminators[self.input_index]) 86 | self.connect(self.output_terminators[self.output_index], (self, self.output_index)) 87 | 88 | def set_input_index(self, input_index): 89 | """ 90 | Change the block to the new input index if the index changed. 91 | 92 | Args: 93 | input_index: the new input index 94 | """ 95 | if self.input_index != input_index: 96 | self.lock() 97 | self._disconnect_current() 98 | self.input_index = input_index 99 | self._connect_current() 100 | self.unlock() 101 | 102 | def set_output_index(self, output_index): 103 | """ 104 | Change the block to the new output index if the index changed. 105 | 106 | Args: 107 | output_index: the new output index 108 | """ 109 | if self.output_index != output_index: 110 | self.lock() 111 | self._disconnect_current() 112 | self.output_index = output_index 113 | self._connect_current() 114 | self.unlock() 115 | 116 | class valve(selector): 117 | """Wrapper for selector with 1 input and 1 output.""" 118 | 119 | def __init__(self, item_size, open): 120 | """ 121 | Constructor for valve. 122 | 123 | Args: 124 | item_size: the size of the gr data stream in bytes 125 | open: true if initial valve state is open 126 | """ 127 | if open: output_index = -1 128 | else: output_index = 0 129 | selector.__init__(self, item_size, 1, 1, 0, output_index) 130 | 131 | def set_open(self, open): 132 | """ 133 | Callback to set open state. 134 | 135 | Args: 136 | open: true to set valve state to open 137 | """ 138 | if open: output_index = -1 139 | else: output_index = 0 140 | self.set_output_index(output_index) 141 | -------------------------------------------------------------------------------- /utils/gr-perf-to-csv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright 2015 Bastian Bloessl 4 | # 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | # 19 | 20 | import sys, time 21 | 22 | from gnuradio import gr, ctrlport 23 | from subprocess import Popen, PIPE 24 | 25 | class MyApp(object): 26 | def __init__(self, args): 27 | p = gr.prefs() 28 | cp_on = p.get_bool("ControlPort", "on", False) 29 | cp_edges = p.get_bool("ControlPort", "edges_list", False) 30 | pcs_on = p.get_bool("PerfCounters", "on", False) 31 | pcs_exported = p.get_bool("PerfCounters", "export", False) 32 | if(not (pcs_on and cp_on and pcs_exported and cp_edges)): 33 | print("Configuration has not turned on all of the appropriate ControlPort features:") 34 | print("\t[ControlPort] on = {0}".format(cp_on)) 35 | print("\t[ControlPort] edges_list = {0}".format(cp_edges)) 36 | print("\t[PerfCounters] on = {0}".format(pcs_on)) 37 | print("\t[PerfCounters] export = {0}".format(pcs_exported)) 38 | exit(1) 39 | 40 | from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient 41 | GNURadioControlPortClient(args, 'thrift', self.run) 42 | 43 | def run(self, client): 44 | input_name = lambda x: x+"::avg input % full" 45 | 46 | tmplist = [] 47 | knobs = client.getKnobs([]) 48 | for k in knobs: 49 | propname = k.split("::") 50 | blockname = propname[0] 51 | keyname = propname[1] 52 | if(blockname not in tmplist): 53 | # only take gr_blocks (no hier_block2) 54 | if(knobs.has_key(input_name(blockname))): 55 | tmplist.append(blockname) 56 | 57 | blocks = tmplist 58 | blocks.sort() 59 | 60 | # print csv header 61 | print(",".join(blocks)) 62 | 63 | knobs = map(lambda x: client.Knob("%s::reset_perf_counters" % x), blocks) 64 | client.setKnobs(knobs) 65 | 66 | # let the flow graph run for some time 67 | time.sleep(60) 68 | 69 | ## get work time for all blocks 70 | kl = map(lambda x: "%s::total work time" % x, blocks) 71 | wrk_knobs = client.getKnobs(kl) 72 | 73 | work_times = dict(zip( 74 | map(lambda x: x.split("::")[0], wrk_knobs.keys()), 75 | map(lambda x: x.value, wrk_knobs.values()))) 76 | 77 | print(",".join(map(lambda x: str(x[1]), sorted(work_times.items())))) 78 | 79 | p = Popen("uptime", stdout=PIPE, close_fds=True, shell=True) 80 | print(p.stdout.read()) 81 | 82 | MyApp(sys.argv) 83 | --------------------------------------------------------------------------------