├── CMakeLists.txt ├── LICENSE ├── MANIFEST.md ├── README.md ├── apps └── CMakeLists.txt ├── cmake ├── Modules │ ├── CMakeParseArgumentsCopy.cmake │ ├── correctiqConfig.cmake │ └── targetConfig.cmake.in └── cmake_uninstall.cmake.in ├── docs ├── CMakeLists.txt ├── Getting rid of that center frequency spike in gnuradio.pdf ├── README.correctiq └── doxygen │ ├── CMakeLists.txt │ ├── Doxyfile.in │ ├── Doxyfile.swig_doc.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 │ ├── swig_doc.py │ └── update_pydoc.py ├── examples ├── basic_receive_flowgraph.grc ├── dcoffset_test.grc └── dcoffset_test.py ├── grc ├── CMakeLists.txt ├── correctiq_SwapIQ.block.yml ├── correctiq_correctiq.block.yml ├── correctiq_correctiq_auto.block.yml └── correctiq_correctiq_man.block.yml ├── include └── correctiq │ ├── CMakeLists.txt │ ├── SwapIQ.h │ ├── api.h │ ├── correctiq.h │ ├── correctiq_auto.h │ └── correctiq_man.h ├── lib ├── CMakeLists.txt ├── SwapIQ_impl.cc ├── SwapIQ_impl.h ├── clSComplex.h ├── correctiq_auto_impl.cc ├── correctiq_auto_impl.h ├── correctiq_impl.cc ├── correctiq_impl.h ├── correctiq_man_impl.cc └── correctiq_man_impl.h └── python ├── CMakeLists.txt ├── __init__.py └── bindings ├── CMakeLists.txt ├── README.md ├── SwapIQ_python.cc ├── bind_oot_file.py ├── correctiq_auto_python.cc ├── correctiq_man_python.cc ├── correctiq_python.cc ├── docstrings ├── README.md ├── SwapIQ_pydoc_template.h ├── correctiq_auto_pydoc_template.h ├── correctiq_man_pydoc_template.h └── correctiq_pydoc_template.h ├── header_utils.py └── python_bindings.cc /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012,2014,2016,2018 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-correctiq 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | 21 | ######################################################################## 22 | # Project setup 23 | ######################################################################## 24 | cmake_minimum_required(VERSION 3.8) 25 | project(gr-correctiq CXX C) 26 | enable_testing() 27 | 28 | # Install to PyBOMBS target prefix if defined 29 | if(DEFINED ENV{PYBOMBS_PREFIX}) 30 | set(CMAKE_INSTALL_PREFIX $ENV{PYBOMBS_PREFIX}) 31 | message(STATUS "PyBOMBS installed GNU Radio. Setting CMAKE_INSTALL_PREFIX to $ENV{PYBOMBS_PREFIX}") 32 | endif() 33 | 34 | # Select the release build type by default to get optimization flags 35 | if(NOT CMAKE_BUILD_TYPE) 36 | set(CMAKE_BUILD_TYPE "Release") 37 | message(STATUS "Build type not specified: defaulting to release.") 38 | endif(NOT CMAKE_BUILD_TYPE) 39 | set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") 40 | 41 | # Make sure our local CMake Modules path comes first 42 | list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/Modules) 43 | 44 | # Set the version information here 45 | set(VERSION_MAJOR 3) 46 | set(VERSION_API 0) 47 | set(VERSION_ABI 0) 48 | set(VERSION_PATCH git) 49 | 50 | cmake_policy(SET CMP0011 NEW) 51 | 52 | # Enable generation of compile_commands.json for code completion engines 53 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 54 | 55 | ######################################################################## 56 | # Compiler specific setup 57 | ######################################################################## 58 | if((CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR 59 | CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 60 | AND NOT WIN32) 61 | #http://gcc.gnu.org/wiki/Visibility 62 | add_definitions(-fvisibility=hidden) 63 | endif() 64 | 65 | IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") 66 | SET(CMAKE_CXX_STANDARD 11) 67 | ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 68 | SET(CMAKE_CXX_STANDARD 11) 69 | ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") 70 | SET(CMAKE_CXX_STANDARD 11) 71 | ELSE() 72 | message(WARNING "C++ standard could not be set because compiler is not GNU, Clang or MSVC.") 73 | ENDIF() 74 | 75 | IF(CMAKE_C_COMPILER_ID STREQUAL "GNU") 76 | SET(CMAKE_C_STANDARD 11) 77 | ELSEIF(CMAKE_C_COMPILER_ID MATCHES "Clang") 78 | SET(CMAKE_C_STANDARD 11) 79 | ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "MSVC") 80 | SET(CMAKE_C_STANDARD 11) 81 | ELSE() 82 | message(WARNING "C standard could not be set because compiler is not GNU, Clang or MSVC.") 83 | ENDIF() 84 | 85 | ######################################################################## 86 | # Disable complex math NaN/INFO range checking for performance 87 | ######################################################################## 88 | include(CheckCXXCompilerFlag) 89 | check_cxx_compiler_flag(-fcx-limited-range HAVE_CX_LIMITED_RANGE) 90 | if(HAVE_CX_LIMITED_RANGE) 91 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcx-limited-range") 92 | endif(HAVE_CX_LIMITED_RANGE) 93 | 94 | ######################################################################## 95 | # Install directories 96 | ######################################################################## 97 | include(FindPkgConfig) 98 | find_package(Gnuradio "3.9" REQUIRED) 99 | 100 | include(GrVersion) 101 | 102 | include(GrPlatform) #define LIB_SUFFIX 103 | 104 | if(NOT CMAKE_MODULES_DIR) 105 | set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake) 106 | endif(NOT CMAKE_MODULES_DIR) 107 | 108 | set(GR_INCLUDE_DIR include/correctiq) 109 | set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/correctiq) 110 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) 111 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) 112 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) 113 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) 114 | 115 | ######################################################################## 116 | # On Apple only, set install name and use rpath correctly, if not already set 117 | ######################################################################## 118 | if(APPLE) 119 | if(NOT CMAKE_INSTALL_NAME_DIR) 120 | set(CMAKE_INSTALL_NAME_DIR 121 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 122 | PATH "Library Install Name Destination Directory" FORCE) 123 | endif(NOT CMAKE_INSTALL_NAME_DIR) 124 | if(NOT CMAKE_INSTALL_RPATH) 125 | set(CMAKE_INSTALL_RPATH 126 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 127 | PATH "Library Install RPath" FORCE) 128 | endif(NOT CMAKE_INSTALL_RPATH) 129 | if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 130 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE 131 | BOOL "Do Build Using Library Install RPath" FORCE) 132 | endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 133 | endif(APPLE) 134 | 135 | ######################################################################## 136 | # Find gnuradio build dependencies 137 | ######################################################################## 138 | find_package(Doxygen) 139 | 140 | ######################################################################## 141 | # PyBind11 Related 142 | ######################################################################## 143 | 144 | find_package(pybind11 REQUIRED) 145 | execute_process( 146 | COMMAND "${PYTHON_EXECUTABLE}" -c 147 | "try:\n import numpy\n import os\n inc_path = numpy.get_include()\n if os.path.exists(os.path.join(inc_path, 'numpy', 'arrayobject.h')):\n print(inc_path, end='')\nexcept:\n pass" 148 | OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR) 149 | 150 | ######################################################################## 151 | # Setup doxygen option 152 | ######################################################################## 153 | if(DOXYGEN_FOUND) 154 | option(ENABLE_DOXYGEN "Build docs using Doxygen" ON) 155 | else(DOXYGEN_FOUND) 156 | option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) 157 | endif(DOXYGEN_FOUND) 158 | 159 | ######################################################################## 160 | # Create uninstall target 161 | ######################################################################## 162 | configure_file( 163 | ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 164 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 165 | @ONLY) 166 | 167 | add_custom_target(uninstall 168 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 169 | ) 170 | 171 | 172 | ######################################################################## 173 | # Add subdirectories 174 | ######################################################################## 175 | add_subdirectory(include/correctiq) 176 | add_subdirectory(lib) 177 | add_subdirectory(apps) 178 | add_subdirectory(docs) 179 | # NOTE: manually update below to use GRC to generate C++ flowgraphs w/o python 180 | if(ENABLE_PYTHON) 181 | message(STATUS "PYTHON and GRC components are enabled") 182 | add_subdirectory(python) 183 | add_subdirectory(grc) 184 | else(ENABLE_PYTHON) 185 | message(STATUS "PYTHON and GRC components are disabled") 186 | endif(ENABLE_PYTHON) 187 | 188 | ######################################################################## 189 | # Install cmake search helper for this library 190 | ######################################################################## 191 | 192 | install(FILES cmake/Modules/correctiqConfig.cmake 193 | DESTINATION ${CMAKE_MODULES_DIR}/correctiq 194 | ) 195 | -------------------------------------------------------------------------------- /MANIFEST.md: -------------------------------------------------------------------------------- 1 | title: The CORRECTIQ OOT Module 2 | brief: Short description of gr-correctiq 3 | tags: # Tags are arbitrary, but look at CGRAN what other authors are using 4 | - sdr 5 | author: 6 | - Author Name 7 | copyright_owner: 8 | - Copyright Owner 1 9 | license: 10 | #repo: # Put the URL of the repository here, or leave blank for default 11 | #website: # If you have a separate project website, put it here 12 | #icon: # Put a URL to a square image here that will be used as an icon on CGRAN 13 | --- 14 | A longer, multi-line description of gr-correctiq. 15 | You may use some *basic* Markdown here. 16 | If left empty, it will try to find a README file instead. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gr-correctiq 2 | Finally, a GNURadio block to remove that IQ DC spike just like some software and drivers do! Just drop it in your flowgraph after your 3 | radio source and rock on. No more offset tuning to get rid of that spike, now you can use the whole bandwidth. 4 | 5 | Update: 6 | 7 | Added 2 new blocks. One that starts with auto-learning then switches to standard DC offset with the results to avoid any potential filtering. This block takes frequency and upstream (radio-side) gain as parameters and if they change auto-recalibrates. The second block is just a manual offset block that can be used for manual tuning. 8 | 9 | ## Building 10 | Build is pretty standard: 11 | 12 | mkdir build 13 | 14 | cd build 15 | 16 | cmake .. 17 | 18 | make 19 | 20 | make install 21 | 22 | ldconfig 23 | 24 | ## Parameters 25 | None. Complex in, complex out. 26 | -------------------------------------------------------------------------------- /apps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file was generated by gr_modtool, a tool from the GNU Radio framework 4 | # This file is a part of gr-correctiq 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | 21 | include(GrPython) 22 | 23 | GR_PYTHON_INSTALL( 24 | PROGRAMS 25 | DESTINATION bin 26 | ) 27 | -------------------------------------------------------------------------------- /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/correctiqConfig.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_CORRECTIQ correctiq) 3 | 4 | FIND_PATH( 5 | CORRECTIQ_INCLUDE_DIRS 6 | NAMES correctiq/api.h 7 | HINTS $ENV{CORRECTIQ_DIR}/include 8 | ${PC_CORRECTIQ_INCLUDEDIR} 9 | PATHS ${CMAKE_INSTALL_PREFIX}/include 10 | /usr/local/include 11 | /usr/include 12 | ) 13 | 14 | FIND_LIBRARY( 15 | CORRECTIQ_LIBRARIES 16 | NAMES gnuradio-correctiq 17 | HINTS $ENV{CORRECTIQ_DIR}/lib 18 | ${PC_CORRECTIQ_LIBDIR} 19 | PATHS ${CMAKE_INSTALL_PREFIX}/lib 20 | ${CMAKE_INSTALL_PREFIX}/lib64 21 | /usr/local/lib 22 | /usr/local/lib64 23 | /usr/lib 24 | /usr/lib64 25 | ) 26 | 27 | include("${CMAKE_CURRENT_LIST_DIR}/correctiqTarget.cmake") 28 | 29 | INCLUDE(FindPackageHandleStandardArgs) 30 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(CORRECTIQ DEFAULT_MSG CORRECTIQ_LIBRARIES CORRECTIQ_INCLUDE_DIRS) 31 | MARK_AS_ADVANCED(CORRECTIQ_LIBRARIES CORRECTIQ_INCLUDE_DIRS) 32 | -------------------------------------------------------------------------------- /cmake/Modules/targetConfig.cmake.in: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | include(CMakeFindDependencyMacro) 21 | 22 | set(target_deps "@TARGET_DEPENDENCIES@") 23 | foreach(dep IN LISTS target_deps) 24 | find_dependency(${dep}) 25 | endforeach() 26 | include("${CMAKE_CURRENT_LIST_DIR}/@TARGET@Targets.cmake") 27 | -------------------------------------------------------------------------------- /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-correctiq 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/Getting rid of that center frequency spike in gnuradio.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostop14/gr-correctiq/f1189bf9f1b4e27daa0c1fe69c6464a39cdf51c5/docs/Getting rid of that center frequency spike in gnuradio.pdf -------------------------------------------------------------------------------- /docs/README.correctiq: -------------------------------------------------------------------------------- 1 | This is the correctiq-write-a-block package meant as a guide to building 2 | out-of-tree packages. To use the correctiq blocks, the Python namespaces 3 | is in 'correctiq', which is imported as: 4 | 5 | import correctiq 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(correctiq) 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-correctiq 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-correctiq 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-correctiq 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-correctiq 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/generated/indexsuper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # Generated Thu Jun 11 18:43:54 2009 by generateDS.py. 5 | # 6 | 7 | 8 | import sys 9 | 10 | from xml.dom import minidom 11 | from xml.dom import Node 12 | 13 | # 14 | # User methods 15 | # 16 | # Calls to the methods in these classes are generated by generateDS.py. 17 | # You can replace these methods by re-implementing the following class 18 | # in a module named generatedssuper.py. 19 | 20 | try: 21 | from generatedssuper import GeneratedsSuper 22 | except ImportError as exp: 23 | 24 | class GeneratedsSuper(object): 25 | def format_string(self, input_data, input_name=''): 26 | return input_data 27 | def format_integer(self, input_data, input_name=''): 28 | return '%d' % input_data 29 | def format_float(self, input_data, input_name=''): 30 | return '%f' % input_data 31 | def format_double(self, input_data, input_name=''): 32 | return '%e' % input_data 33 | def format_boolean(self, input_data, input_name=''): 34 | return '%s' % input_data 35 | 36 | 37 | # 38 | # If you have installed IPython you can uncomment and use the following. 39 | # IPython is available from http://ipython.scipy.org/. 40 | # 41 | 42 | ## from IPython.Shell import IPShellEmbed 43 | ## args = '' 44 | ## ipshell = IPShellEmbed(args, 45 | ## banner = 'Dropping into IPython', 46 | ## exit_msg = 'Leaving Interpreter, back to program.') 47 | 48 | # Then use the following line where and when you want to drop into the 49 | # IPython shell: 50 | # ipshell(' -- Entering ipshell.\nHit Ctrl-D to exit') 51 | 52 | # 53 | # Globals 54 | # 55 | 56 | ExternalEncoding = 'ascii' 57 | 58 | # 59 | # Support/utility functions. 60 | # 61 | 62 | def showIndent(outfile, level): 63 | for idx in range(level): 64 | outfile.write(' ') 65 | 66 | def quote_xml(inStr): 67 | s1 = (isinstance(inStr, str) and inStr or 68 | '%s' % inStr) 69 | s1 = s1.replace('&', '&') 70 | s1 = s1.replace('<', '<') 71 | s1 = s1.replace('>', '>') 72 | return s1 73 | 74 | def quote_attrib(inStr): 75 | s1 = (isinstance(inStr, str) and inStr or 76 | '%s' % inStr) 77 | s1 = s1.replace('&', '&') 78 | s1 = s1.replace('<', '<') 79 | s1 = s1.replace('>', '>') 80 | if '"' in s1: 81 | if "'" in s1: 82 | s1 = '"%s"' % s1.replace('"', """) 83 | else: 84 | s1 = "'%s'" % s1 85 | else: 86 | s1 = '"%s"' % s1 87 | return s1 88 | 89 | def quote_python(inStr): 90 | s1 = inStr 91 | if s1.find("'") == -1: 92 | if s1.find('\n') == -1: 93 | return "'%s'" % s1 94 | else: 95 | return "'''%s'''" % s1 96 | else: 97 | if s1.find('"') != -1: 98 | s1 = s1.replace('"', '\\"') 99 | if s1.find('\n') == -1: 100 | return '"%s"' % s1 101 | else: 102 | return '"""%s"""' % s1 103 | 104 | 105 | class MixedContainer(object): 106 | # Constants for category: 107 | CategoryNone = 0 108 | CategoryText = 1 109 | CategorySimple = 2 110 | CategoryComplex = 3 111 | # Constants for content_type: 112 | TypeNone = 0 113 | TypeText = 1 114 | TypeString = 2 115 | TypeInteger = 3 116 | TypeFloat = 4 117 | TypeDecimal = 5 118 | TypeDouble = 6 119 | TypeBoolean = 7 120 | def __init__(self, category, content_type, name, value): 121 | self.category = category 122 | self.content_type = content_type 123 | self.name = name 124 | self.value = value 125 | def getCategory(self): 126 | return self.category 127 | def getContenttype(self, content_type): 128 | return self.content_type 129 | def getValue(self): 130 | return self.value 131 | def getName(self): 132 | return self.name 133 | def export(self, outfile, level, name, namespace): 134 | if self.category == MixedContainer.CategoryText: 135 | outfile.write(self.value) 136 | elif self.category == MixedContainer.CategorySimple: 137 | self.exportSimple(outfile, level, name) 138 | else: # category == MixedContainer.CategoryComplex 139 | self.value.export(outfile, level, namespace,name) 140 | def exportSimple(self, outfile, level, name): 141 | if self.content_type == MixedContainer.TypeString: 142 | outfile.write('<%s>%s' % (self.name, self.value, self.name)) 143 | elif self.content_type == MixedContainer.TypeInteger or \ 144 | self.content_type == MixedContainer.TypeBoolean: 145 | outfile.write('<%s>%d' % (self.name, self.value, self.name)) 146 | elif self.content_type == MixedContainer.TypeFloat or \ 147 | self.content_type == MixedContainer.TypeDecimal: 148 | outfile.write('<%s>%f' % (self.name, self.value, self.name)) 149 | elif self.content_type == MixedContainer.TypeDouble: 150 | outfile.write('<%s>%g' % (self.name, self.value, self.name)) 151 | def exportLiteral(self, outfile, level, name): 152 | if self.category == MixedContainer.CategoryText: 153 | showIndent(outfile, level) 154 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ 155 | (self.category, self.content_type, self.name, self.value)) 156 | elif self.category == MixedContainer.CategorySimple: 157 | showIndent(outfile, level) 158 | outfile.write('MixedContainer(%d, %d, "%s", "%s"),\n' % \ 159 | (self.category, self.content_type, self.name, self.value)) 160 | else: # category == MixedContainer.CategoryComplex 161 | showIndent(outfile, level) 162 | outfile.write('MixedContainer(%d, %d, "%s",\n' % \ 163 | (self.category, self.content_type, self.name,)) 164 | self.value.exportLiteral(outfile, level + 1) 165 | showIndent(outfile, level) 166 | outfile.write(')\n') 167 | 168 | 169 | class _MemberSpec(object): 170 | def __init__(self, name='', data_type='', container=0): 171 | self.name = name 172 | self.data_type = data_type 173 | self.container = container 174 | def set_name(self, name): self.name = name 175 | def get_name(self): return self.name 176 | def set_data_type(self, data_type): self.data_type = data_type 177 | def get_data_type(self): return self.data_type 178 | def set_container(self, container): self.container = container 179 | def get_container(self): return self.container 180 | 181 | 182 | # 183 | # Data representation classes. 184 | # 185 | 186 | class DoxygenType(GeneratedsSuper): 187 | subclass = None 188 | superclass = None 189 | def __init__(self, version=None, compound=None): 190 | self.version = version 191 | if compound is None: 192 | self.compound = [] 193 | else: 194 | self.compound = compound 195 | def factory(*args_, **kwargs_): 196 | if DoxygenType.subclass: 197 | return DoxygenType.subclass(*args_, **kwargs_) 198 | else: 199 | return DoxygenType(*args_, **kwargs_) 200 | factory = staticmethod(factory) 201 | def get_compound(self): return self.compound 202 | def set_compound(self, compound): self.compound = compound 203 | def add_compound(self, value): self.compound.append(value) 204 | def insert_compound(self, index, value): self.compound[index] = value 205 | def get_version(self): return self.version 206 | def set_version(self, version): self.version = version 207 | def export(self, outfile, level, namespace_='', name_='DoxygenType', namespacedef_=''): 208 | showIndent(outfile, level) 209 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 210 | self.exportAttributes(outfile, level, namespace_, name_='DoxygenType') 211 | if self.hasContent_(): 212 | outfile.write('>\n') 213 | self.exportChildren(outfile, level + 1, namespace_, name_) 214 | showIndent(outfile, level) 215 | outfile.write('\n' % (namespace_, name_)) 216 | else: 217 | outfile.write(' />\n') 218 | def exportAttributes(self, outfile, level, namespace_='', name_='DoxygenType'): 219 | outfile.write(' version=%s' % (self.format_string(quote_attrib(self.version).encode(ExternalEncoding), input_name='version'), )) 220 | def exportChildren(self, outfile, level, namespace_='', name_='DoxygenType'): 221 | for compound_ in self.compound: 222 | compound_.export(outfile, level, namespace_, name_='compound') 223 | def hasContent_(self): 224 | if ( 225 | self.compound is not None 226 | ): 227 | return True 228 | else: 229 | return False 230 | def exportLiteral(self, outfile, level, name_='DoxygenType'): 231 | level += 1 232 | self.exportLiteralAttributes(outfile, level, name_) 233 | if self.hasContent_(): 234 | self.exportLiteralChildren(outfile, level, name_) 235 | def exportLiteralAttributes(self, outfile, level, name_): 236 | if self.version is not None: 237 | showIndent(outfile, level) 238 | outfile.write('version = %s,\n' % (self.version,)) 239 | def exportLiteralChildren(self, outfile, level, name_): 240 | showIndent(outfile, level) 241 | outfile.write('compound=[\n') 242 | level += 1 243 | for compound in self.compound: 244 | showIndent(outfile, level) 245 | outfile.write('model_.compound(\n') 246 | compound.exportLiteral(outfile, level, name_='compound') 247 | showIndent(outfile, level) 248 | outfile.write('),\n') 249 | level -= 1 250 | showIndent(outfile, level) 251 | outfile.write('],\n') 252 | def build(self, node_): 253 | attrs = node_.attributes 254 | self.buildAttributes(attrs) 255 | for child_ in node_.childNodes: 256 | nodeName_ = child_.nodeName.split(':')[-1] 257 | self.buildChildren(child_, nodeName_) 258 | def buildAttributes(self, attrs): 259 | if attrs.get('version'): 260 | self.version = attrs.get('version').value 261 | def buildChildren(self, child_, nodeName_): 262 | if child_.nodeType == Node.ELEMENT_NODE and \ 263 | nodeName_ == 'compound': 264 | obj_ = CompoundType.factory() 265 | obj_.build(child_) 266 | self.compound.append(obj_) 267 | # end class DoxygenType 268 | 269 | 270 | class CompoundType(GeneratedsSuper): 271 | subclass = None 272 | superclass = None 273 | def __init__(self, kind=None, refid=None, name=None, member=None): 274 | self.kind = kind 275 | self.refid = refid 276 | self.name = name 277 | if member is None: 278 | self.member = [] 279 | else: 280 | self.member = member 281 | def factory(*args_, **kwargs_): 282 | if CompoundType.subclass: 283 | return CompoundType.subclass(*args_, **kwargs_) 284 | else: 285 | return CompoundType(*args_, **kwargs_) 286 | factory = staticmethod(factory) 287 | def get_name(self): return self.name 288 | def set_name(self, name): self.name = name 289 | def get_member(self): return self.member 290 | def set_member(self, member): self.member = member 291 | def add_member(self, value): self.member.append(value) 292 | def insert_member(self, index, value): self.member[index] = value 293 | def get_kind(self): return self.kind 294 | def set_kind(self, kind): self.kind = kind 295 | def get_refid(self): return self.refid 296 | def set_refid(self, refid): self.refid = refid 297 | def export(self, outfile, level, namespace_='', name_='CompoundType', namespacedef_=''): 298 | showIndent(outfile, level) 299 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 300 | self.exportAttributes(outfile, level, namespace_, name_='CompoundType') 301 | if self.hasContent_(): 302 | outfile.write('>\n') 303 | self.exportChildren(outfile, level + 1, namespace_, name_) 304 | showIndent(outfile, level) 305 | outfile.write('\n' % (namespace_, name_)) 306 | else: 307 | outfile.write(' />\n') 308 | def exportAttributes(self, outfile, level, namespace_='', name_='CompoundType'): 309 | outfile.write(' kind=%s' % (quote_attrib(self.kind), )) 310 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) 311 | def exportChildren(self, outfile, level, namespace_='', name_='CompoundType'): 312 | if self.name is not None: 313 | showIndent(outfile, level) 314 | outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) 315 | for member_ in self.member: 316 | member_.export(outfile, level, namespace_, name_='member') 317 | def hasContent_(self): 318 | if ( 319 | self.name is not None or 320 | self.member is not None 321 | ): 322 | return True 323 | else: 324 | return False 325 | def exportLiteral(self, outfile, level, name_='CompoundType'): 326 | level += 1 327 | self.exportLiteralAttributes(outfile, level, name_) 328 | if self.hasContent_(): 329 | self.exportLiteralChildren(outfile, level, name_) 330 | def exportLiteralAttributes(self, outfile, level, name_): 331 | if self.kind is not None: 332 | showIndent(outfile, level) 333 | outfile.write('kind = "%s",\n' % (self.kind,)) 334 | if self.refid is not None: 335 | showIndent(outfile, level) 336 | outfile.write('refid = %s,\n' % (self.refid,)) 337 | def exportLiteralChildren(self, outfile, level, name_): 338 | showIndent(outfile, level) 339 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) 340 | showIndent(outfile, level) 341 | outfile.write('member=[\n') 342 | level += 1 343 | for member in self.member: 344 | showIndent(outfile, level) 345 | outfile.write('model_.member(\n') 346 | member.exportLiteral(outfile, level, name_='member') 347 | showIndent(outfile, level) 348 | outfile.write('),\n') 349 | level -= 1 350 | showIndent(outfile, level) 351 | outfile.write('],\n') 352 | def build(self, node_): 353 | attrs = node_.attributes 354 | self.buildAttributes(attrs) 355 | for child_ in node_.childNodes: 356 | nodeName_ = child_.nodeName.split(':')[-1] 357 | self.buildChildren(child_, nodeName_) 358 | def buildAttributes(self, attrs): 359 | if attrs.get('kind'): 360 | self.kind = attrs.get('kind').value 361 | if attrs.get('refid'): 362 | self.refid = attrs.get('refid').value 363 | def buildChildren(self, child_, nodeName_): 364 | if child_.nodeType == Node.ELEMENT_NODE and \ 365 | nodeName_ == 'name': 366 | name_ = '' 367 | for text__content_ in child_.childNodes: 368 | name_ += text__content_.nodeValue 369 | self.name = name_ 370 | elif child_.nodeType == Node.ELEMENT_NODE and \ 371 | nodeName_ == 'member': 372 | obj_ = MemberType.factory() 373 | obj_.build(child_) 374 | self.member.append(obj_) 375 | # end class CompoundType 376 | 377 | 378 | class MemberType(GeneratedsSuper): 379 | subclass = None 380 | superclass = None 381 | def __init__(self, kind=None, refid=None, name=None): 382 | self.kind = kind 383 | self.refid = refid 384 | self.name = name 385 | def factory(*args_, **kwargs_): 386 | if MemberType.subclass: 387 | return MemberType.subclass(*args_, **kwargs_) 388 | else: 389 | return MemberType(*args_, **kwargs_) 390 | factory = staticmethod(factory) 391 | def get_name(self): return self.name 392 | def set_name(self, name): self.name = name 393 | def get_kind(self): return self.kind 394 | def set_kind(self, kind): self.kind = kind 395 | def get_refid(self): return self.refid 396 | def set_refid(self, refid): self.refid = refid 397 | def export(self, outfile, level, namespace_='', name_='MemberType', namespacedef_=''): 398 | showIndent(outfile, level) 399 | outfile.write('<%s%s %s' % (namespace_, name_, namespacedef_, )) 400 | self.exportAttributes(outfile, level, namespace_, name_='MemberType') 401 | if self.hasContent_(): 402 | outfile.write('>\n') 403 | self.exportChildren(outfile, level + 1, namespace_, name_) 404 | showIndent(outfile, level) 405 | outfile.write('\n' % (namespace_, name_)) 406 | else: 407 | outfile.write(' />\n') 408 | def exportAttributes(self, outfile, level, namespace_='', name_='MemberType'): 409 | outfile.write(' kind=%s' % (quote_attrib(self.kind), )) 410 | outfile.write(' refid=%s' % (self.format_string(quote_attrib(self.refid).encode(ExternalEncoding), input_name='refid'), )) 411 | def exportChildren(self, outfile, level, namespace_='', name_='MemberType'): 412 | if self.name is not None: 413 | showIndent(outfile, level) 414 | outfile.write('<%sname>%s\n' % (namespace_, self.format_string(quote_xml(self.name).encode(ExternalEncoding), input_name='name'), namespace_)) 415 | def hasContent_(self): 416 | if ( 417 | self.name is not None 418 | ): 419 | return True 420 | else: 421 | return False 422 | def exportLiteral(self, outfile, level, name_='MemberType'): 423 | level += 1 424 | self.exportLiteralAttributes(outfile, level, name_) 425 | if self.hasContent_(): 426 | self.exportLiteralChildren(outfile, level, name_) 427 | def exportLiteralAttributes(self, outfile, level, name_): 428 | if self.kind is not None: 429 | showIndent(outfile, level) 430 | outfile.write('kind = "%s",\n' % (self.kind,)) 431 | if self.refid is not None: 432 | showIndent(outfile, level) 433 | outfile.write('refid = %s,\n' % (self.refid,)) 434 | def exportLiteralChildren(self, outfile, level, name_): 435 | showIndent(outfile, level) 436 | outfile.write('name=%s,\n' % quote_python(self.name).encode(ExternalEncoding)) 437 | def build(self, node_): 438 | attrs = node_.attributes 439 | self.buildAttributes(attrs) 440 | for child_ in node_.childNodes: 441 | nodeName_ = child_.nodeName.split(':')[-1] 442 | self.buildChildren(child_, nodeName_) 443 | def buildAttributes(self, attrs): 444 | if attrs.get('kind'): 445 | self.kind = attrs.get('kind').value 446 | if attrs.get('refid'): 447 | self.refid = attrs.get('refid').value 448 | def buildChildren(self, child_, nodeName_): 449 | if child_.nodeType == Node.ELEMENT_NODE and \ 450 | nodeName_ == 'name': 451 | name_ = '' 452 | for text__content_ in child_.childNodes: 453 | name_ += text__content_.nodeValue 454 | self.name = name_ 455 | # end class MemberType 456 | 457 | 458 | USAGE_TEXT = """ 459 | Usage: python .py [ -s ] 460 | Options: 461 | -s Use the SAX parser, not the minidom parser. 462 | """ 463 | 464 | def usage(): 465 | print(USAGE_TEXT) 466 | sys.exit(1) 467 | 468 | 469 | def parse(inFileName): 470 | doc = minidom.parse(inFileName) 471 | rootNode = doc.documentElement 472 | rootObj = DoxygenType.factory() 473 | rootObj.build(rootNode) 474 | # Enable Python to collect the space used by the DOM. 475 | doc = None 476 | sys.stdout.write('\n') 477 | rootObj.export(sys.stdout, 0, name_="doxygenindex", 478 | namespacedef_='') 479 | return rootObj 480 | 481 | 482 | def parseString(inString): 483 | doc = minidom.parseString(inString) 484 | rootNode = doc.documentElement 485 | rootObj = DoxygenType.factory() 486 | rootObj.build(rootNode) 487 | # Enable Python to collect the space used by the DOM. 488 | doc = None 489 | sys.stdout.write('\n') 490 | rootObj.export(sys.stdout, 0, name_="doxygenindex", 491 | namespacedef_='') 492 | return rootObj 493 | 494 | 495 | def parseLiteral(inFileName): 496 | doc = minidom.parse(inFileName) 497 | rootNode = doc.documentElement 498 | rootObj = DoxygenType.factory() 499 | rootObj.build(rootNode) 500 | # Enable Python to collect the space used by the DOM. 501 | doc = None 502 | sys.stdout.write('from index import *\n\n') 503 | sys.stdout.write('rootObj = doxygenindex(\n') 504 | rootObj.exportLiteral(sys.stdout, 0, name_="doxygenindex") 505 | sys.stdout.write(')\n') 506 | return rootObj 507 | 508 | 509 | def main(): 510 | args = sys.argv[1:] 511 | if len(args) == 1: 512 | parse(args[0]) 513 | else: 514 | usage() 515 | 516 | 517 | 518 | 519 | if __name__ == '__main__': 520 | main() 521 | #import pdb 522 | #pdb.run('main()') 523 | -------------------------------------------------------------------------------- /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-correctiq 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 CORRECTIQ C++ Signal Processing Blocks 3 | * \brief All C++ blocks that can be used from the CORRECTIQ 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 CORRECTIQ Block 4 | 5 | This is the intro page for the Doxygen manual generated for the CORRECTIQ 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/swig_doc.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 gr-correctiq 6 | # 7 | # GNU Radio is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 3, or (at your option) 10 | # any later version. 11 | # 12 | # GNU Radio is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with GNU Radio; see the file COPYING. If not, write to 19 | # the Free Software Foundation, Inc., 51 Franklin Street, 20 | # Boston, MA 02110-1301, USA. 21 | # 22 | """ 23 | Creates the swig_doc.i SWIG interface file. 24 | Execute using: python swig_doc.py xml_path outputfilename 25 | 26 | The file instructs SWIG to transfer the doxygen comments into the 27 | python docstrings. 28 | 29 | """ 30 | from __future__ import unicode_literals 31 | 32 | import sys, time 33 | 34 | from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile 35 | from doxyxml import DoxyOther, base 36 | 37 | def py_name(name): 38 | bits = name.split('_') 39 | return '_'.join(bits[1:]) 40 | 41 | def make_name(name): 42 | bits = name.split('_') 43 | return bits[0] + '_make_' + '_'.join(bits[1:]) 44 | 45 | 46 | class Block(object): 47 | """ 48 | Checks if doxyxml produced objects correspond to a gnuradio block. 49 | """ 50 | 51 | @classmethod 52 | def includes(cls, item): 53 | if not isinstance(item, DoxyClass): 54 | return False 55 | # Check for a parsing error. 56 | if item.error(): 57 | return False 58 | friendname = make_name(item.name()) 59 | is_a_block = item.has_member(friendname, DoxyFriend) 60 | # But now sometimes the make function isn't a friend so check again. 61 | if not is_a_block: 62 | is_a_block = di.has_member(friendname, DoxyFunction) 63 | return is_a_block 64 | 65 | class Block2(object): 66 | """ 67 | Checks if doxyxml produced objects correspond to a new style 68 | gnuradio block. 69 | """ 70 | 71 | @classmethod 72 | def includes(cls, item): 73 | if not isinstance(item, DoxyClass): 74 | return False 75 | # Check for a parsing error. 76 | if item.error(): 77 | return False 78 | is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther) 79 | return is_a_block2 80 | 81 | 82 | def utoascii(text): 83 | """ 84 | Convert unicode text into ascii and escape quotes and backslashes. 85 | """ 86 | if text is None: 87 | return '' 88 | out = text.encode('ascii', 'replace') 89 | # swig will require us to replace blackslash with 4 backslashes 90 | out = out.replace(b'\\', b'\\\\\\\\') 91 | out = out.replace(b'"', b'\\"').decode('ascii') 92 | return str(out) 93 | 94 | 95 | def combine_descriptions(obj): 96 | """ 97 | Combines the brief and detailed descriptions of an object together. 98 | """ 99 | description = [] 100 | bd = obj.brief_description.strip() 101 | dd = obj.detailed_description.strip() 102 | if bd: 103 | description.append(bd) 104 | if dd: 105 | description.append(dd) 106 | return utoascii('\n\n'.join(description)).strip() 107 | 108 | def format_params(parameteritems): 109 | output = ['Args:'] 110 | template = ' {0} : {1}' 111 | for pi in parameteritems: 112 | output.append(template.format(pi.name, pi.description)) 113 | return '\n'.join(output) 114 | 115 | entry_templ = '%feature("docstring") {name} "{docstring}"' 116 | def make_entry(obj, name=None, templ="{description}", description=None, params=[]): 117 | """ 118 | Create a docstring entry for a swig interface file. 119 | 120 | obj - a doxyxml object from which documentation will be extracted. 121 | name - the name of the C object (defaults to obj.name()) 122 | templ - an optional template for the docstring containing only one 123 | variable named 'description'. 124 | description - if this optional variable is set then it's value is 125 | used as the description instead of extracting it from obj. 126 | """ 127 | if name is None: 128 | name=obj.name() 129 | if "operator " in name: 130 | return '' 131 | if description is None: 132 | description = combine_descriptions(obj) 133 | if params: 134 | description += '\n\n' 135 | description += utoascii(format_params(params)) 136 | docstring = templ.format(description=description) 137 | if not docstring: 138 | return '' 139 | return entry_templ.format( 140 | name=name, 141 | docstring=docstring, 142 | ) 143 | 144 | 145 | def make_func_entry(func, name=None, description=None, params=None): 146 | """ 147 | Create a function docstring entry for a swig interface file. 148 | 149 | func - a doxyxml object from which documentation will be extracted. 150 | name - the name of the C object (defaults to func.name()) 151 | description - if this optional variable is set then it's value is 152 | used as the description instead of extracting it from func. 153 | params - a parameter list that overrides using func.params. 154 | """ 155 | #if params is None: 156 | # params = func.params 157 | #params = [prm.declname for prm in params] 158 | #if params: 159 | # sig = "Params: (%s)" % ", ".join(params) 160 | #else: 161 | # sig = "Params: (NONE)" 162 | #templ = "{description}\n\n" + sig 163 | #return make_entry(func, name=name, templ=utoascii(templ), 164 | # description=description) 165 | return make_entry(func, name=name, description=description, params=params) 166 | 167 | 168 | def make_class_entry(klass, description=None, ignored_methods=[], params=None): 169 | """ 170 | Create a class docstring for a swig interface file. 171 | """ 172 | if params is None: 173 | params = klass.params 174 | output = [] 175 | output.append(make_entry(klass, description=description, params=params)) 176 | for func in klass.in_category(DoxyFunction): 177 | if func.name() not in ignored_methods: 178 | name = klass.name() + '::' + func.name() 179 | output.append(make_func_entry(func, name=name)) 180 | return "\n\n".join(output) 181 | 182 | 183 | def make_block_entry(di, block): 184 | """ 185 | Create class and function docstrings of a gnuradio block for a 186 | swig interface file. 187 | """ 188 | descriptions = [] 189 | # Get the documentation associated with the class. 190 | class_desc = combine_descriptions(block) 191 | if class_desc: 192 | descriptions.append(class_desc) 193 | # Get the documentation associated with the make function 194 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 195 | make_func_desc = combine_descriptions(make_func) 196 | if make_func_desc: 197 | descriptions.append(make_func_desc) 198 | # Get the documentation associated with the file 199 | try: 200 | block_file = di.get_member(block.name() + ".h", DoxyFile) 201 | file_desc = combine_descriptions(block_file) 202 | if file_desc: 203 | descriptions.append(file_desc) 204 | except base.Base.NoSuchMember: 205 | # Don't worry if we can't find a matching file. 206 | pass 207 | # And join them all together to make a super duper description. 208 | super_description = "\n\n".join(descriptions) 209 | # Associate the combined description with the class and 210 | # the make function. 211 | output = [] 212 | output.append(make_class_entry(block, description=super_description)) 213 | output.append(make_func_entry(make_func, description=super_description, 214 | params=block.params)) 215 | return "\n\n".join(output) 216 | 217 | def make_block2_entry(di, block): 218 | """ 219 | Create class and function docstrings of a new style gnuradio block for a 220 | swig interface file. 221 | """ 222 | descriptions = [] 223 | # For new style blocks all the relevant documentation should be 224 | # associated with the 'make' method. 225 | class_description = combine_descriptions(block) 226 | make_func = block.get_member('make', DoxyFunction) 227 | make_description = combine_descriptions(make_func) 228 | description = class_description + "\n\nConstructor Specific Documentation:\n\n" + make_description 229 | # Associate the combined description with the class and 230 | # the make function. 231 | output = [] 232 | output.append(make_class_entry( 233 | block, description=description, 234 | ignored_methods=['make'], params=make_func.params)) 235 | makename = block.name() + '::make' 236 | output.append(make_func_entry( 237 | make_func, name=makename, description=description, 238 | params=make_func.params)) 239 | return "\n\n".join(output) 240 | 241 | def make_swig_interface_file(di, swigdocfilename, custom_output=None): 242 | 243 | output = [""" 244 | /* 245 | * This file was automatically generated using swig_doc.py. 246 | * 247 | * Any changes to it will be lost next time it is regenerated. 248 | */ 249 | """] 250 | 251 | if custom_output is not None: 252 | output.append(custom_output) 253 | 254 | # Create docstrings for the blocks. 255 | blocks = di.in_category(Block) 256 | blocks2 = di.in_category(Block2) 257 | 258 | make_funcs = set([]) 259 | for block in blocks: 260 | try: 261 | make_func = di.get_member(make_name(block.name()), DoxyFunction) 262 | # Don't want to risk writing to output twice. 263 | if make_func.name() not in make_funcs: 264 | make_funcs.add(make_func.name()) 265 | output.append(make_block_entry(di, block)) 266 | except block.ParsingError: 267 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) 268 | raise 269 | 270 | for block in blocks2: 271 | try: 272 | make_func = block.get_member('make', DoxyFunction) 273 | make_func_name = block.name() +'::make' 274 | # Don't want to risk writing to output twice. 275 | if make_func_name not in make_funcs: 276 | make_funcs.add(make_func_name) 277 | output.append(make_block2_entry(di, block)) 278 | except block.ParsingError: 279 | sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) 280 | raise 281 | 282 | # Create docstrings for functions 283 | # Don't include the make functions since they have already been dealt with. 284 | funcs = [f for f in di.in_category(DoxyFunction) 285 | if f.name() not in make_funcs and not f.name().startswith('std::')] 286 | for f in funcs: 287 | try: 288 | output.append(make_func_entry(f)) 289 | except f.ParsingError: 290 | sys.stderr.write('Parsing error for function {0}\n'.format(f.name())) 291 | 292 | # Create docstrings for classes 293 | block_names = [block.name() for block in blocks] 294 | block_names += [block.name() for block in blocks2] 295 | klasses = [k for k in di.in_category(DoxyClass) 296 | if k.name() not in block_names and not k.name().startswith('std::')] 297 | for k in klasses: 298 | try: 299 | output.append(make_class_entry(k)) 300 | except k.ParsingError: 301 | sys.stderr.write('Parsing error for class {0}\n'.format(k.name())) 302 | 303 | # Docstrings are not created for anything that is not a function or a class. 304 | # If this excludes anything important please add it here. 305 | 306 | output = "\n\n".join(output) 307 | 308 | swig_doc = open(swigdocfilename, 'w') 309 | swig_doc.write(output) 310 | swig_doc.close() 311 | 312 | if __name__ == "__main__": 313 | # Parse command line options and set up doxyxml. 314 | err_msg = "Execute using: python swig_doc.py xml_path outputfilename" 315 | if len(sys.argv) != 3: 316 | raise Exception(err_msg) 317 | xml_path = sys.argv[1] 318 | swigdocfilename = sys.argv[2] 319 | di = DoxyIndex(xml_path) 320 | 321 | # gnuradio.gr.msq_queue.insert_tail and delete_head create errors unless docstrings are defined! 322 | # This is presumably a bug in SWIG. 323 | #msg_q = di.get_member(u'gr_msg_queue', DoxyClass) 324 | #insert_tail = msg_q.get_member(u'insert_tail', DoxyFunction) 325 | #delete_head = msg_q.get_member(u'delete_head', DoxyFunction) 326 | output = [] 327 | #output.append(make_func_entry(insert_tail, name='gr_py_msg_queue__insert_tail')) 328 | #output.append(make_func_entry(delete_head, name='gr_py_msg_queue__delete_head')) 329 | custom_output = "\n\n".join(output) 330 | 331 | # Generate the docstrings interface file. 332 | make_swig_interface_file(di, swigdocfilename, custom_output=custom_output) 333 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/basic_receive_flowgraph.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | category: '[GRC Hier Blocks]' 5 | cmake_opt: '' 6 | comment: '' 7 | copyright: '' 8 | description: '' 9 | gen_cmake: 'On' 10 | gen_linking: dynamic 11 | generate_options: qt_gui 12 | hier_block_src_path: '.:' 13 | id: basic_receive_flowgraph 14 | max_nouts: '0' 15 | output_language: python 16 | placement: (0,0) 17 | qt_qss_theme: '' 18 | realtime_scheduling: '' 19 | run: 'True' 20 | run_command: '{python} -u {filename}' 21 | run_options: prompt 22 | sizing_mode: fixed 23 | thread_safe_setters: '' 24 | title: '' 25 | window_size: '' 26 | states: 27 | bus_sink: false 28 | bus_source: false 29 | bus_structure: null 30 | coordinate: [8, 8] 31 | rotation: 0 32 | state: enabled 33 | 34 | blocks: 35 | - name: center_freq 36 | id: variable_qtgui_entry 37 | parameters: 38 | comment: '' 39 | gui_hint: 0,0,1,1 40 | label: Frequency 41 | type: real 42 | value: 95.7e6 43 | states: 44 | bus_sink: false 45 | bus_source: false 46 | bus_structure: null 47 | coordinate: [320, 12] 48 | rotation: 0 49 | state: enabled 50 | - name: gain 51 | id: variable 52 | parameters: 53 | comment: 'RX: 0-40 in 8 dB steps 54 | 55 | TX: 0-47 in 1 dB steps' 56 | value: '24' 57 | states: 58 | bus_sink: false 59 | bus_source: false 60 | bus_structure: null 61 | coordinate: [632, 12] 62 | rotation: 0 63 | state: enabled 64 | - name: samp_rate 65 | id: variable 66 | parameters: 67 | comment: '' 68 | value: 2.4e6 69 | states: 70 | bus_sink: false 71 | bus_source: false 72 | bus_structure: null 73 | coordinate: [8, 92] 74 | rotation: 0 75 | state: enabled 76 | - name: correctiq_correctiq_0 77 | id: correctiq_correctiq 78 | parameters: 79 | affinity: '' 80 | alias: '' 81 | comment: '' 82 | maxoutbuf: '0' 83 | minoutbuf: '0' 84 | states: 85 | bus_sink: false 86 | bus_source: false 87 | bus_structure: null 88 | coordinate: [328, 280] 89 | rotation: 0 90 | state: enabled 91 | - name: osmosdr_source_0 92 | id: osmosdr_source 93 | parameters: 94 | affinity: '' 95 | alias: '' 96 | ant0: '' 97 | ant1: '' 98 | ant10: '' 99 | ant11: '' 100 | ant12: '' 101 | ant13: '' 102 | ant14: '' 103 | ant15: '' 104 | ant16: '' 105 | ant17: '' 106 | ant18: '' 107 | ant19: '' 108 | ant2: '' 109 | ant20: '' 110 | ant21: '' 111 | ant22: '' 112 | ant23: '' 113 | ant24: '' 114 | ant25: '' 115 | ant26: '' 116 | ant27: '' 117 | ant28: '' 118 | ant29: '' 119 | ant3: '' 120 | ant30: '' 121 | ant31: '' 122 | ant4: '' 123 | ant5: '' 124 | ant6: '' 125 | ant7: '' 126 | ant8: '' 127 | ant9: '' 128 | args: '' 129 | bb_gain0: '0' 130 | bb_gain1: '20' 131 | bb_gain10: '20' 132 | bb_gain11: '20' 133 | bb_gain12: '20' 134 | bb_gain13: '20' 135 | bb_gain14: '20' 136 | bb_gain15: '20' 137 | bb_gain16: '20' 138 | bb_gain17: '20' 139 | bb_gain18: '20' 140 | bb_gain19: '20' 141 | bb_gain2: '20' 142 | bb_gain20: '20' 143 | bb_gain21: '20' 144 | bb_gain22: '20' 145 | bb_gain23: '20' 146 | bb_gain24: '20' 147 | bb_gain25: '20' 148 | bb_gain26: '20' 149 | bb_gain27: '20' 150 | bb_gain28: '20' 151 | bb_gain29: '20' 152 | bb_gain3: '20' 153 | bb_gain30: '20' 154 | bb_gain31: '20' 155 | bb_gain4: '20' 156 | bb_gain5: '20' 157 | bb_gain6: '20' 158 | bb_gain7: '20' 159 | bb_gain8: '20' 160 | bb_gain9: '20' 161 | bw0: '0' 162 | bw1: '0' 163 | bw10: '0' 164 | bw11: '0' 165 | bw12: '0' 166 | bw13: '0' 167 | bw14: '0' 168 | bw15: '0' 169 | bw16: '0' 170 | bw17: '0' 171 | bw18: '0' 172 | bw19: '0' 173 | bw2: '0' 174 | bw20: '0' 175 | bw21: '0' 176 | bw22: '0' 177 | bw23: '0' 178 | bw24: '0' 179 | bw25: '0' 180 | bw26: '0' 181 | bw27: '0' 182 | bw28: '0' 183 | bw29: '0' 184 | bw3: '0' 185 | bw30: '0' 186 | bw31: '0' 187 | bw4: '0' 188 | bw5: '0' 189 | bw6: '0' 190 | bw7: '0' 191 | bw8: '0' 192 | bw9: '0' 193 | clock_source0: '' 194 | clock_source1: '' 195 | clock_source2: '' 196 | clock_source3: '' 197 | clock_source4: '' 198 | clock_source5: '' 199 | clock_source6: '' 200 | clock_source7: '' 201 | comment: HackRF Config 202 | corr0: '0' 203 | corr1: '0' 204 | corr10: '0' 205 | corr11: '0' 206 | corr12: '0' 207 | corr13: '0' 208 | corr14: '0' 209 | corr15: '0' 210 | corr16: '0' 211 | corr17: '0' 212 | corr18: '0' 213 | corr19: '0' 214 | corr2: '0' 215 | corr20: '0' 216 | corr21: '0' 217 | corr22: '0' 218 | corr23: '0' 219 | corr24: '0' 220 | corr25: '0' 221 | corr26: '0' 222 | corr27: '0' 223 | corr28: '0' 224 | corr29: '0' 225 | corr3: '0' 226 | corr30: '0' 227 | corr31: '0' 228 | corr4: '0' 229 | corr5: '0' 230 | corr6: '0' 231 | corr7: '0' 232 | corr8: '0' 233 | corr9: '0' 234 | dc_offset_mode0: '0' 235 | dc_offset_mode1: '0' 236 | dc_offset_mode10: '0' 237 | dc_offset_mode11: '0' 238 | dc_offset_mode12: '0' 239 | dc_offset_mode13: '0' 240 | dc_offset_mode14: '0' 241 | dc_offset_mode15: '0' 242 | dc_offset_mode16: '0' 243 | dc_offset_mode17: '0' 244 | dc_offset_mode18: '0' 245 | dc_offset_mode19: '0' 246 | dc_offset_mode2: '0' 247 | dc_offset_mode20: '0' 248 | dc_offset_mode21: '0' 249 | dc_offset_mode22: '0' 250 | dc_offset_mode23: '0' 251 | dc_offset_mode24: '0' 252 | dc_offset_mode25: '0' 253 | dc_offset_mode26: '0' 254 | dc_offset_mode27: '0' 255 | dc_offset_mode28: '0' 256 | dc_offset_mode29: '0' 257 | dc_offset_mode3: '0' 258 | dc_offset_mode30: '0' 259 | dc_offset_mode31: '0' 260 | dc_offset_mode4: '0' 261 | dc_offset_mode5: '0' 262 | dc_offset_mode6: '0' 263 | dc_offset_mode7: '0' 264 | dc_offset_mode8: '0' 265 | dc_offset_mode9: '0' 266 | freq0: center_freq 267 | freq1: 100e6 268 | freq10: 100e6 269 | freq11: 100e6 270 | freq12: 100e6 271 | freq13: 100e6 272 | freq14: 100e6 273 | freq15: 100e6 274 | freq16: 100e6 275 | freq17: 100e6 276 | freq18: 100e6 277 | freq19: 100e6 278 | freq2: 100e6 279 | freq20: 100e6 280 | freq21: 100e6 281 | freq22: 100e6 282 | freq23: 100e6 283 | freq24: 100e6 284 | freq25: 100e6 285 | freq26: 100e6 286 | freq27: 100e6 287 | freq28: 100e6 288 | freq29: 100e6 289 | freq3: 100e6 290 | freq30: 100e6 291 | freq31: 100e6 292 | freq4: 100e6 293 | freq5: 100e6 294 | freq6: 100e6 295 | freq7: 100e6 296 | freq8: 100e6 297 | freq9: 100e6 298 | gain0: gain 299 | gain1: '10' 300 | gain10: '10' 301 | gain11: '10' 302 | gain12: '10' 303 | gain13: '10' 304 | gain14: '10' 305 | gain15: '10' 306 | gain16: '10' 307 | gain17: '10' 308 | gain18: '10' 309 | gain19: '10' 310 | gain2: '10' 311 | gain20: '10' 312 | gain21: '10' 313 | gain22: '10' 314 | gain23: '10' 315 | gain24: '10' 316 | gain25: '10' 317 | gain26: '10' 318 | gain27: '10' 319 | gain28: '10' 320 | gain29: '10' 321 | gain3: '10' 322 | gain30: '10' 323 | gain31: '10' 324 | gain4: '10' 325 | gain5: '10' 326 | gain6: '10' 327 | gain7: '10' 328 | gain8: '10' 329 | gain9: '10' 330 | gain_mode0: 'False' 331 | gain_mode1: 'False' 332 | gain_mode10: 'False' 333 | gain_mode11: 'False' 334 | gain_mode12: 'False' 335 | gain_mode13: 'False' 336 | gain_mode14: 'False' 337 | gain_mode15: 'False' 338 | gain_mode16: 'False' 339 | gain_mode17: 'False' 340 | gain_mode18: 'False' 341 | gain_mode19: 'False' 342 | gain_mode2: 'False' 343 | gain_mode20: 'False' 344 | gain_mode21: 'False' 345 | gain_mode22: 'False' 346 | gain_mode23: 'False' 347 | gain_mode24: 'False' 348 | gain_mode25: 'False' 349 | gain_mode26: 'False' 350 | gain_mode27: 'False' 351 | gain_mode28: 'False' 352 | gain_mode29: 'False' 353 | gain_mode3: 'False' 354 | gain_mode30: 'False' 355 | gain_mode31: 'False' 356 | gain_mode4: 'False' 357 | gain_mode5: 'False' 358 | gain_mode6: 'False' 359 | gain_mode7: 'False' 360 | gain_mode8: 'False' 361 | gain_mode9: 'False' 362 | if_gain0: '0' 363 | if_gain1: '20' 364 | if_gain10: '20' 365 | if_gain11: '20' 366 | if_gain12: '20' 367 | if_gain13: '20' 368 | if_gain14: '20' 369 | if_gain15: '20' 370 | if_gain16: '20' 371 | if_gain17: '20' 372 | if_gain18: '20' 373 | if_gain19: '20' 374 | if_gain2: '20' 375 | if_gain20: '20' 376 | if_gain21: '20' 377 | if_gain22: '20' 378 | if_gain23: '20' 379 | if_gain24: '20' 380 | if_gain25: '20' 381 | if_gain26: '20' 382 | if_gain27: '20' 383 | if_gain28: '20' 384 | if_gain29: '20' 385 | if_gain3: '20' 386 | if_gain30: '20' 387 | if_gain31: '20' 388 | if_gain4: '20' 389 | if_gain5: '20' 390 | if_gain6: '20' 391 | if_gain7: '20' 392 | if_gain8: '20' 393 | if_gain9: '20' 394 | iq_balance_mode0: '0' 395 | iq_balance_mode1: '0' 396 | iq_balance_mode10: '0' 397 | iq_balance_mode11: '0' 398 | iq_balance_mode12: '0' 399 | iq_balance_mode13: '0' 400 | iq_balance_mode14: '0' 401 | iq_balance_mode15: '0' 402 | iq_balance_mode16: '0' 403 | iq_balance_mode17: '0' 404 | iq_balance_mode18: '0' 405 | iq_balance_mode19: '0' 406 | iq_balance_mode2: '0' 407 | iq_balance_mode20: '0' 408 | iq_balance_mode21: '0' 409 | iq_balance_mode22: '0' 410 | iq_balance_mode23: '0' 411 | iq_balance_mode24: '0' 412 | iq_balance_mode25: '0' 413 | iq_balance_mode26: '0' 414 | iq_balance_mode27: '0' 415 | iq_balance_mode28: '0' 416 | iq_balance_mode29: '0' 417 | iq_balance_mode3: '0' 418 | iq_balance_mode30: '0' 419 | iq_balance_mode31: '0' 420 | iq_balance_mode4: '0' 421 | iq_balance_mode5: '0' 422 | iq_balance_mode6: '0' 423 | iq_balance_mode7: '0' 424 | iq_balance_mode8: '0' 425 | iq_balance_mode9: '0' 426 | maxoutbuf: '0' 427 | minoutbuf: '0' 428 | nchan: '1' 429 | num_mboards: '1' 430 | sample_rate: samp_rate 431 | sync: sync 432 | time_source0: '' 433 | time_source1: '' 434 | time_source2: '' 435 | time_source3: '' 436 | time_source4: '' 437 | time_source5: '' 438 | time_source6: '' 439 | time_source7: '' 440 | type: fc32 441 | states: 442 | bus_sink: false 443 | bus_source: false 444 | bus_structure: null 445 | coordinate: [16, 212] 446 | rotation: 0 447 | state: enabled 448 | - name: qtgui_freq_sink_x_0 449 | id: qtgui_freq_sink_x 450 | parameters: 451 | affinity: '' 452 | alias: '' 453 | alpha1: '1.0' 454 | alpha10: '1.0' 455 | alpha2: '1.0' 456 | alpha3: '1.0' 457 | alpha4: '1.0' 458 | alpha5: '1.0' 459 | alpha6: '1.0' 460 | alpha7: '1.0' 461 | alpha8: '1.0' 462 | alpha9: '1.0' 463 | autoscale: 'False' 464 | average: '1.0' 465 | axislabels: 'True' 466 | bw: samp_rate 467 | color1: '"blue"' 468 | color10: '"dark blue"' 469 | color2: '"red"' 470 | color3: '"green"' 471 | color4: '"black"' 472 | color5: '"cyan"' 473 | color6: '"magenta"' 474 | color7: '"yellow"' 475 | color8: '"dark red"' 476 | color9: '"dark green"' 477 | comment: '' 478 | ctrlpanel: 'False' 479 | fc: center_freq 480 | fftsize: '1024' 481 | freqhalf: 'True' 482 | grid: 'False' 483 | gui_hint: 1,0,2,2 484 | label: Relative Gain 485 | label1: '' 486 | label10: '' 487 | label2: '' 488 | label3: '' 489 | label4: '' 490 | label5: '' 491 | label6: '' 492 | label7: '' 493 | label8: '' 494 | label9: '' 495 | legend: 'True' 496 | maxoutbuf: '0' 497 | minoutbuf: '0' 498 | name: '""' 499 | nconnections: '1' 500 | showports: 'True' 501 | tr_chan: '0' 502 | tr_level: '0.0' 503 | tr_mode: qtgui.TRIG_MODE_FREE 504 | tr_tag: '""' 505 | type: complex 506 | units: dB 507 | update_time: '0.10' 508 | width1: '1' 509 | width10: '1' 510 | width2: '1' 511 | width3: '1' 512 | width4: '1' 513 | width5: '1' 514 | width6: '1' 515 | width7: '1' 516 | width8: '1' 517 | width9: '1' 518 | wintype: firdes.WIN_BLACKMAN_hARRIS 519 | ymax: '10' 520 | ymin: '-90' 521 | states: 522 | bus_sink: false 523 | bus_source: false 524 | bus_structure: null 525 | coordinate: [648, 204] 526 | rotation: 0 527 | state: enabled 528 | - name: qtgui_waterfall_sink_x_0 529 | id: qtgui_waterfall_sink_x 530 | parameters: 531 | affinity: '' 532 | alias: '' 533 | alpha1: '1.0' 534 | alpha10: '1.0' 535 | alpha2: '1.0' 536 | alpha3: '1.0' 537 | alpha4: '1.0' 538 | alpha5: '1.0' 539 | alpha6: '1.0' 540 | alpha7: '1.0' 541 | alpha8: '1.0' 542 | alpha9: '1.0' 543 | axislabels: 'True' 544 | bw: samp_rate 545 | color1: '0' 546 | color10: '0' 547 | color2: '0' 548 | color3: '0' 549 | color4: '0' 550 | color5: '0' 551 | color6: '0' 552 | color7: '0' 553 | color8: '0' 554 | color9: '0' 555 | comment: '' 556 | fc: center_freq 557 | fftsize: '1024' 558 | freqhalf: 'True' 559 | grid: 'False' 560 | gui_hint: 3,0,1,2 561 | int_max: '10' 562 | int_min: '-90' 563 | label1: '' 564 | label10: '' 565 | label2: '' 566 | label3: '' 567 | label4: '' 568 | label5: '' 569 | label6: '' 570 | label7: '' 571 | label8: '' 572 | label9: '' 573 | legend: 'True' 574 | maxoutbuf: '0' 575 | minoutbuf: '0' 576 | name: '""' 577 | nconnections: '1' 578 | showports: 'True' 579 | type: complex 580 | update_time: '0.10' 581 | wintype: firdes.WIN_BLACKMAN_hARRIS 582 | states: 583 | bus_sink: false 584 | bus_source: false 585 | bus_structure: null 586 | coordinate: [648, 300] 587 | rotation: 0 588 | state: enabled 589 | 590 | connections: 591 | - [correctiq_correctiq_0, '0', qtgui_freq_sink_x_0, '0'] 592 | - [correctiq_correctiq_0, '0', qtgui_waterfall_sink_x_0, '0'] 593 | - [osmosdr_source_0, '0', correctiq_correctiq_0, '0'] 594 | 595 | metadata: 596 | file_format: 1 597 | -------------------------------------------------------------------------------- /examples/dcoffset_test.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: Custom 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: dcoffset_test 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | states: 27 | bus_sink: false 28 | bus_source: false 29 | bus_structure: null 30 | coordinate: [8, 8] 31 | rotation: 0 32 | state: enabled 33 | 34 | blocks: 35 | - name: amp_on 36 | id: variable 37 | parameters: 38 | comment: '' 39 | value: '14' 40 | states: 41 | bus_sink: false 42 | bus_source: false 43 | bus_structure: null 44 | coordinate: [1192, 12] 45 | rotation: 0 46 | state: enabled 47 | - name: center_freq 48 | id: variable_qtgui_entry 49 | parameters: 50 | comment: '' 51 | gui_hint: 0,0,1,1 52 | label: Center Frequency 53 | type: real 54 | value: 95.7e6 55 | states: 56 | bus_sink: false 57 | bus_source: false 58 | bus_structure: null 59 | coordinate: [208, 36] 60 | rotation: 0 61 | state: enabled 62 | - name: gain 63 | id: variable_qtgui_range 64 | parameters: 65 | comment: 'Hackrf:0-40 in 8 dB steps 66 | 67 | Airspy: 0-21' 68 | gui_hint: 0,1,1,1 69 | label: Gain 70 | min_len: '200' 71 | orient: QtCore.Qt.Horizontal 72 | rangeType: float 73 | start: '0' 74 | step: '8' 75 | stop: '40' 76 | value: '16' 77 | widget: counter_slider 78 | states: 79 | bus_sink: false 80 | bus_source: false 81 | bus_structure: null 82 | coordinate: [713, 36] 83 | rotation: 0 84 | state: enabled 85 | - name: imag 86 | id: variable_qtgui_range 87 | parameters: 88 | comment: '' 89 | gui_hint: 1,1,1,1 90 | label: '' 91 | min_len: '200' 92 | orient: QtCore.Qt.Horizontal 93 | rangeType: float 94 | start: '-0.1' 95 | step: '0.0001' 96 | stop: '0.1' 97 | value: '-0.004100' 98 | widget: counter_slider 99 | states: 100 | bus_sink: false 101 | bus_source: false 102 | bus_structure: null 103 | coordinate: [560, 43] 104 | rotation: 0 105 | state: enabled 106 | - name: real 107 | id: variable_qtgui_range 108 | parameters: 109 | comment: '' 110 | gui_hint: 1,0,1,1 111 | label: '' 112 | min_len: '200' 113 | orient: QtCore.Qt.Horizontal 114 | rangeType: float 115 | start: '-0.1' 116 | step: '0.0001' 117 | stop: '0.1' 118 | value: '-0.011900' 119 | widget: counter_slider 120 | states: 121 | bus_sink: false 122 | bus_source: false 123 | bus_structure: null 124 | coordinate: [384, 43] 125 | rotation: 0 126 | state: enabled 127 | - name: samp_rate 128 | id: variable 129 | parameters: 130 | comment: '' 131 | value: 2.4e6 132 | states: 133 | bus_sink: false 134 | bus_source: false 135 | bus_structure: null 136 | coordinate: [8, 160] 137 | rotation: 0 138 | state: enabled 139 | - name: blocks_add_const_vxx_1_0 140 | id: blocks_add_const_vxx 141 | parameters: 142 | affinity: '' 143 | alias: '' 144 | comment: '' 145 | const: real + 1j * imag 146 | maxoutbuf: '0' 147 | minoutbuf: '0' 148 | type: complex 149 | vlen: '1' 150 | states: 151 | bus_sink: false 152 | bus_source: false 153 | bus_structure: null 154 | coordinate: [512, 300] 155 | rotation: 0 156 | state: enabled 157 | - name: correctiq_correctiq_1 158 | id: correctiq_correctiq 159 | parameters: 160 | affinity: '' 161 | alias: '' 162 | comment: '' 163 | maxoutbuf: '0' 164 | minoutbuf: '0' 165 | states: 166 | bus_sink: false 167 | bus_source: false 168 | bus_structure: null 169 | coordinate: [592, 552] 170 | rotation: 0 171 | state: enabled 172 | - name: correctiq_correctiq_auto_0 173 | id: correctiq_correctiq_auto 174 | parameters: 175 | affinity: '' 176 | alias: '' 177 | comment: '' 178 | freq: center_freq 179 | gain: gain 180 | maxoutbuf: '0' 181 | minoutbuf: '0' 182 | samp_rate: samp_rate 183 | syncWindow: '2' 184 | states: 185 | bus_sink: false 186 | bus_source: false 187 | bus_structure: null 188 | coordinate: [528, 456] 189 | rotation: 0 190 | state: enabled 191 | - name: correctiq_correctiq_man_0 192 | id: correctiq_correctiq_man 193 | parameters: 194 | affinity: '' 195 | alias: '' 196 | comment: '' 197 | imag: imag 198 | maxoutbuf: '0' 199 | minoutbuf: '0' 200 | real: real 201 | states: 202 | bus_sink: false 203 | bus_source: false 204 | bus_structure: null 205 | coordinate: [520, 372] 206 | rotation: 0 207 | state: enabled 208 | - name: osmosdr_source_0 209 | id: osmosdr_source 210 | parameters: 211 | affinity: '' 212 | alias: '' 213 | ant0: '' 214 | ant1: '' 215 | ant10: '' 216 | ant11: '' 217 | ant12: '' 218 | ant13: '' 219 | ant14: '' 220 | ant15: '' 221 | ant16: '' 222 | ant17: '' 223 | ant18: '' 224 | ant19: '' 225 | ant2: '' 226 | ant20: '' 227 | ant21: '' 228 | ant22: '' 229 | ant23: '' 230 | ant24: '' 231 | ant25: '' 232 | ant26: '' 233 | ant27: '' 234 | ant28: '' 235 | ant29: '' 236 | ant3: '' 237 | ant30: '' 238 | ant31: '' 239 | ant4: '' 240 | ant5: '' 241 | ant6: '' 242 | ant7: '' 243 | ant8: '' 244 | ant9: '' 245 | args: rtl 246 | bb_gain0: '0' 247 | bb_gain1: '20' 248 | bb_gain10: '20' 249 | bb_gain11: '20' 250 | bb_gain12: '20' 251 | bb_gain13: '20' 252 | bb_gain14: '20' 253 | bb_gain15: '20' 254 | bb_gain16: '20' 255 | bb_gain17: '20' 256 | bb_gain18: '20' 257 | bb_gain19: '20' 258 | bb_gain2: '20' 259 | bb_gain20: '20' 260 | bb_gain21: '20' 261 | bb_gain22: '20' 262 | bb_gain23: '20' 263 | bb_gain24: '20' 264 | bb_gain25: '20' 265 | bb_gain26: '20' 266 | bb_gain27: '20' 267 | bb_gain28: '20' 268 | bb_gain29: '20' 269 | bb_gain3: '20' 270 | bb_gain30: '20' 271 | bb_gain31: '20' 272 | bb_gain4: '20' 273 | bb_gain5: '20' 274 | bb_gain6: '20' 275 | bb_gain7: '20' 276 | bb_gain8: '20' 277 | bb_gain9: '20' 278 | bw0: '0' 279 | bw1: '0' 280 | bw10: '0' 281 | bw11: '0' 282 | bw12: '0' 283 | bw13: '0' 284 | bw14: '0' 285 | bw15: '0' 286 | bw16: '0' 287 | bw17: '0' 288 | bw18: '0' 289 | bw19: '0' 290 | bw2: '0' 291 | bw20: '0' 292 | bw21: '0' 293 | bw22: '0' 294 | bw23: '0' 295 | bw24: '0' 296 | bw25: '0' 297 | bw26: '0' 298 | bw27: '0' 299 | bw28: '0' 300 | bw29: '0' 301 | bw3: '0' 302 | bw30: '0' 303 | bw31: '0' 304 | bw4: '0' 305 | bw5: '0' 306 | bw6: '0' 307 | bw7: '0' 308 | bw8: '0' 309 | bw9: '0' 310 | clock_source0: '' 311 | clock_source1: '' 312 | clock_source2: '' 313 | clock_source3: '' 314 | clock_source4: '' 315 | clock_source5: '' 316 | clock_source6: '' 317 | clock_source7: '' 318 | comment: HackRF Config 319 | corr0: '0' 320 | corr1: '0' 321 | corr10: '0' 322 | corr11: '0' 323 | corr12: '0' 324 | corr13: '0' 325 | corr14: '0' 326 | corr15: '0' 327 | corr16: '0' 328 | corr17: '0' 329 | corr18: '0' 330 | corr19: '0' 331 | corr2: '0' 332 | corr20: '0' 333 | corr21: '0' 334 | corr22: '0' 335 | corr23: '0' 336 | corr24: '0' 337 | corr25: '0' 338 | corr26: '0' 339 | corr27: '0' 340 | corr28: '0' 341 | corr29: '0' 342 | corr3: '0' 343 | corr30: '0' 344 | corr31: '0' 345 | corr4: '0' 346 | corr5: '0' 347 | corr6: '0' 348 | corr7: '0' 349 | corr8: '0' 350 | corr9: '0' 351 | dc_offset_mode0: '0' 352 | dc_offset_mode1: '0' 353 | dc_offset_mode10: '0' 354 | dc_offset_mode11: '0' 355 | dc_offset_mode12: '0' 356 | dc_offset_mode13: '0' 357 | dc_offset_mode14: '0' 358 | dc_offset_mode15: '0' 359 | dc_offset_mode16: '0' 360 | dc_offset_mode17: '0' 361 | dc_offset_mode18: '0' 362 | dc_offset_mode19: '0' 363 | dc_offset_mode2: '0' 364 | dc_offset_mode20: '0' 365 | dc_offset_mode21: '0' 366 | dc_offset_mode22: '0' 367 | dc_offset_mode23: '0' 368 | dc_offset_mode24: '0' 369 | dc_offset_mode25: '0' 370 | dc_offset_mode26: '0' 371 | dc_offset_mode27: '0' 372 | dc_offset_mode28: '0' 373 | dc_offset_mode29: '0' 374 | dc_offset_mode3: '0' 375 | dc_offset_mode30: '0' 376 | dc_offset_mode31: '0' 377 | dc_offset_mode4: '0' 378 | dc_offset_mode5: '0' 379 | dc_offset_mode6: '0' 380 | dc_offset_mode7: '0' 381 | dc_offset_mode8: '0' 382 | dc_offset_mode9: '0' 383 | freq0: center_freq 384 | freq1: 100e6 385 | freq10: 100e6 386 | freq11: 100e6 387 | freq12: 100e6 388 | freq13: 100e6 389 | freq14: 100e6 390 | freq15: 100e6 391 | freq16: 100e6 392 | freq17: 100e6 393 | freq18: 100e6 394 | freq19: 100e6 395 | freq2: 100e6 396 | freq20: 100e6 397 | freq21: 100e6 398 | freq22: 100e6 399 | freq23: 100e6 400 | freq24: 100e6 401 | freq25: 100e6 402 | freq26: 100e6 403 | freq27: 100e6 404 | freq28: 100e6 405 | freq29: 100e6 406 | freq3: 100e6 407 | freq30: 100e6 408 | freq31: 100e6 409 | freq4: 100e6 410 | freq5: 100e6 411 | freq6: 100e6 412 | freq7: 100e6 413 | freq8: 100e6 414 | freq9: 100e6 415 | gain0: gain 416 | gain1: '10' 417 | gain10: '10' 418 | gain11: '10' 419 | gain12: '10' 420 | gain13: '10' 421 | gain14: '10' 422 | gain15: '10' 423 | gain16: '10' 424 | gain17: '10' 425 | gain18: '10' 426 | gain19: '10' 427 | gain2: '10' 428 | gain20: '10' 429 | gain21: '10' 430 | gain22: '10' 431 | gain23: '10' 432 | gain24: '10' 433 | gain25: '10' 434 | gain26: '10' 435 | gain27: '10' 436 | gain28: '10' 437 | gain29: '10' 438 | gain3: '10' 439 | gain30: '10' 440 | gain31: '10' 441 | gain4: '10' 442 | gain5: '10' 443 | gain6: '10' 444 | gain7: '10' 445 | gain8: '10' 446 | gain9: '10' 447 | gain_mode0: 'False' 448 | gain_mode1: 'False' 449 | gain_mode10: 'False' 450 | gain_mode11: 'False' 451 | gain_mode12: 'False' 452 | gain_mode13: 'False' 453 | gain_mode14: 'False' 454 | gain_mode15: 'False' 455 | gain_mode16: 'False' 456 | gain_mode17: 'False' 457 | gain_mode18: 'False' 458 | gain_mode19: 'False' 459 | gain_mode2: 'False' 460 | gain_mode20: 'False' 461 | gain_mode21: 'False' 462 | gain_mode22: 'False' 463 | gain_mode23: 'False' 464 | gain_mode24: 'False' 465 | gain_mode25: 'False' 466 | gain_mode26: 'False' 467 | gain_mode27: 'False' 468 | gain_mode28: 'False' 469 | gain_mode29: 'False' 470 | gain_mode3: 'False' 471 | gain_mode30: 'False' 472 | gain_mode31: 'False' 473 | gain_mode4: 'False' 474 | gain_mode5: 'False' 475 | gain_mode6: 'False' 476 | gain_mode7: 'False' 477 | gain_mode8: 'False' 478 | gain_mode9: 'False' 479 | if_gain0: '0' 480 | if_gain1: '20' 481 | if_gain10: '20' 482 | if_gain11: '20' 483 | if_gain12: '20' 484 | if_gain13: '20' 485 | if_gain14: '20' 486 | if_gain15: '20' 487 | if_gain16: '20' 488 | if_gain17: '20' 489 | if_gain18: '20' 490 | if_gain19: '20' 491 | if_gain2: '20' 492 | if_gain20: '20' 493 | if_gain21: '20' 494 | if_gain22: '20' 495 | if_gain23: '20' 496 | if_gain24: '20' 497 | if_gain25: '20' 498 | if_gain26: '20' 499 | if_gain27: '20' 500 | if_gain28: '20' 501 | if_gain29: '20' 502 | if_gain3: '20' 503 | if_gain30: '20' 504 | if_gain31: '20' 505 | if_gain4: '20' 506 | if_gain5: '20' 507 | if_gain6: '20' 508 | if_gain7: '20' 509 | if_gain8: '20' 510 | if_gain9: '20' 511 | iq_balance_mode0: '0' 512 | iq_balance_mode1: '0' 513 | iq_balance_mode10: '0' 514 | iq_balance_mode11: '0' 515 | iq_balance_mode12: '0' 516 | iq_balance_mode13: '0' 517 | iq_balance_mode14: '0' 518 | iq_balance_mode15: '0' 519 | iq_balance_mode16: '0' 520 | iq_balance_mode17: '0' 521 | iq_balance_mode18: '0' 522 | iq_balance_mode19: '0' 523 | iq_balance_mode2: '0' 524 | iq_balance_mode20: '0' 525 | iq_balance_mode21: '0' 526 | iq_balance_mode22: '0' 527 | iq_balance_mode23: '0' 528 | iq_balance_mode24: '0' 529 | iq_balance_mode25: '0' 530 | iq_balance_mode26: '0' 531 | iq_balance_mode27: '0' 532 | iq_balance_mode28: '0' 533 | iq_balance_mode29: '0' 534 | iq_balance_mode3: '0' 535 | iq_balance_mode30: '0' 536 | iq_balance_mode31: '0' 537 | iq_balance_mode4: '0' 538 | iq_balance_mode5: '0' 539 | iq_balance_mode6: '0' 540 | iq_balance_mode7: '0' 541 | iq_balance_mode8: '0' 542 | iq_balance_mode9: '0' 543 | maxoutbuf: '0' 544 | minoutbuf: '0' 545 | nchan: '1' 546 | num_mboards: '1' 547 | sample_rate: samp_rate 548 | sync: sync 549 | time_source0: '' 550 | time_source1: '' 551 | time_source2: '' 552 | time_source3: '' 553 | time_source4: '' 554 | time_source5: '' 555 | time_source6: '' 556 | time_source7: '' 557 | type: fc32 558 | states: 559 | bus_sink: false 560 | bus_source: false 561 | bus_structure: null 562 | coordinate: [192, 244] 563 | rotation: 0 564 | state: enabled 565 | - name: qtgui_freq_sink_x_0 566 | id: qtgui_freq_sink_x 567 | parameters: 568 | affinity: '' 569 | alias: '' 570 | alpha1: '1.0' 571 | alpha10: '1.0' 572 | alpha2: '1.0' 573 | alpha3: '1.0' 574 | alpha4: '1.0' 575 | alpha5: '1.0' 576 | alpha6: '1.0' 577 | alpha7: '1.0' 578 | alpha8: '1.0' 579 | alpha9: '1.0' 580 | autoscale: 'False' 581 | average: '0.2' 582 | axislabels: 'True' 583 | bw: samp_rate 584 | color1: '"blue"' 585 | color10: '"dark blue"' 586 | color2: '"red"' 587 | color3: '"green"' 588 | color4: '"black"' 589 | color5: '"cyan"' 590 | color6: '"magenta"' 591 | color7: '"yellow"' 592 | color8: '"dark red"' 593 | color9: '"dark green"' 594 | comment: '' 595 | ctrlpanel: 'False' 596 | fc: center_freq 597 | fftsize: '2048' 598 | freqhalf: 'True' 599 | grid: 'True' 600 | gui_hint: '' 601 | label: Relative Gain 602 | label1: Add Const 603 | label10: '' 604 | label2: Manual Offset 605 | label3: AutoSync Offset 606 | label4: CorrectIQ 607 | label5: '' 608 | label6: '' 609 | label7: '' 610 | label8: '' 611 | label9: '' 612 | legend: 'True' 613 | maxoutbuf: '0' 614 | minoutbuf: '0' 615 | name: '""' 616 | nconnections: '4' 617 | norm_window: 'False' 618 | showports: 'True' 619 | tr_chan: '0' 620 | tr_level: '0.0' 621 | tr_mode: qtgui.TRIG_MODE_FREE 622 | tr_tag: '""' 623 | type: complex 624 | units: dB 625 | update_time: '0.10' 626 | width1: '1' 627 | width10: '1' 628 | width2: '1' 629 | width3: '1' 630 | width4: '1' 631 | width5: '1' 632 | width6: '1' 633 | width7: '1' 634 | width8: '1' 635 | width9: '1' 636 | wintype: window.WIN_BLACKMAN_hARRIS 637 | ymax: '-20' 638 | ymin: '-120' 639 | states: 640 | bus_sink: false 641 | bus_source: false 642 | bus_structure: null 643 | coordinate: [1008, 243] 644 | rotation: 0 645 | state: enabled 646 | - name: qtgui_time_sink_x_0 647 | id: qtgui_time_sink_x 648 | parameters: 649 | affinity: '' 650 | alias: '' 651 | alpha1: '1.0' 652 | alpha10: '1.0' 653 | alpha2: '1.0' 654 | alpha3: '1.0' 655 | alpha4: '1.0' 656 | alpha5: '1.0' 657 | alpha6: '1.0' 658 | alpha7: '1.0' 659 | alpha8: '1.0' 660 | alpha9: '1.0' 661 | autoscale: 'True' 662 | axislabels: 'True' 663 | color1: blue 664 | color10: dark blue 665 | color2: red 666 | color3: green 667 | color4: black 668 | color5: cyan 669 | color6: magenta 670 | color7: yellow 671 | color8: dark red 672 | color9: dark green 673 | comment: '' 674 | ctrlpanel: 'False' 675 | entags: 'True' 676 | grid: 'True' 677 | gui_hint: '' 678 | label1: Add Const I 679 | label10: '' 680 | label2: Add Const Q 681 | label3: Manual CorrectIQ I 682 | label4: Manual CorrectIQ Q 683 | label5: Auto CorrectIQ I 684 | label6: Auto CorrectIQ Q 685 | label7: Full CorrectIQ I 686 | label8: Full CorrectIQ Q 687 | label9: '' 688 | legend: 'True' 689 | marker1: '-1' 690 | marker10: '-1' 691 | marker2: '-1' 692 | marker3: '-1' 693 | marker4: '-1' 694 | marker5: '-1' 695 | marker6: '-1' 696 | marker7: '-1' 697 | marker8: '-1' 698 | marker9: '-1' 699 | name: '""' 700 | nconnections: '4' 701 | size: '2048' 702 | srate: samp_rate 703 | stemplot: 'False' 704 | style1: '1' 705 | style10: '1' 706 | style2: '1' 707 | style3: '1' 708 | style4: '1' 709 | style5: '1' 710 | style6: '1' 711 | style7: '1' 712 | style8: '1' 713 | style9: '1' 714 | tr_chan: '0' 715 | tr_delay: '0' 716 | tr_level: '0.0' 717 | tr_mode: qtgui.TRIG_MODE_FREE 718 | tr_slope: qtgui.TRIG_SLOPE_POS 719 | tr_tag: '""' 720 | type: complex 721 | update_time: '0.10' 722 | width1: '1' 723 | width10: '1' 724 | width2: '1' 725 | width3: '1' 726 | width4: '1' 727 | width5: '1' 728 | width6: '1' 729 | width7: '1' 730 | width8: '1' 731 | width9: '1' 732 | ylabel: Amplitude 733 | ymax: '0.01' 734 | ymin: '-0.01' 735 | yunit: '""' 736 | states: 737 | bus_sink: false 738 | bus_source: false 739 | bus_structure: null 740 | coordinate: [1011, 445] 741 | rotation: 0 742 | state: enabled 743 | 744 | connections: 745 | - [blocks_add_const_vxx_1_0, '0', qtgui_freq_sink_x_0, '0'] 746 | - [blocks_add_const_vxx_1_0, '0', qtgui_time_sink_x_0, '0'] 747 | - [correctiq_correctiq_1, '0', qtgui_freq_sink_x_0, '3'] 748 | - [correctiq_correctiq_1, '0', qtgui_time_sink_x_0, '3'] 749 | - [correctiq_correctiq_auto_0, '0', qtgui_freq_sink_x_0, '2'] 750 | - [correctiq_correctiq_auto_0, '0', qtgui_time_sink_x_0, '2'] 751 | - [correctiq_correctiq_man_0, '0', qtgui_freq_sink_x_0, '1'] 752 | - [correctiq_correctiq_man_0, '0', qtgui_time_sink_x_0, '1'] 753 | - [osmosdr_source_0, '0', blocks_add_const_vxx_1_0, '0'] 754 | - [osmosdr_source_0, '0', correctiq_correctiq_1, '0'] 755 | - [osmosdr_source_0, '0', correctiq_correctiq_auto_0, '0'] 756 | - [osmosdr_source_0, '0', correctiq_correctiq_man_0, '0'] 757 | 758 | metadata: 759 | file_format: 1 760 | -------------------------------------------------------------------------------- /examples/dcoffset_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # 5 | # SPDX-License-Identifier: GPL-3.0 6 | # 7 | # GNU Radio Python Flow Graph 8 | # Title: Dcoffset Test 9 | # GNU Radio version: v3.8.0.0-845-g0901fcb5 10 | 11 | from distutils.version import StrictVersion 12 | 13 | if __name__ == '__main__': 14 | import ctypes 15 | import sys 16 | if sys.platform.startswith('linux'): 17 | try: 18 | x11 = ctypes.cdll.LoadLibrary('libX11.so') 19 | x11.XInitThreads() 20 | except: 21 | print("Warning: failed to XInitThreads()") 22 | 23 | from PyQt5 import Qt 24 | from gnuradio import eng_notation 25 | from gnuradio import qtgui 26 | from gnuradio.filter import firdes 27 | import sip 28 | from gnuradio import blocks 29 | from gnuradio import gr 30 | from gnuradio.fft import window 31 | import sys 32 | import signal 33 | from argparse import ArgumentParser 34 | from gnuradio.eng_arg import eng_float, intx 35 | from gnuradio.qtgui import Range, RangeWidget 36 | from PyQt5 import QtCore 37 | import correctiq 38 | import osmosdr 39 | import time 40 | 41 | from gnuradio import qtgui 42 | 43 | class dcoffset_test(gr.top_block, Qt.QWidget): 44 | 45 | def __init__(self): 46 | gr.top_block.__init__(self, "Dcoffset Test", catch_exceptions=True) 47 | Qt.QWidget.__init__(self) 48 | self.setWindowTitle("Dcoffset Test") 49 | qtgui.util.check_set_qss() 50 | try: 51 | self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) 52 | except: 53 | pass 54 | self.top_scroll_layout = Qt.QVBoxLayout() 55 | self.setLayout(self.top_scroll_layout) 56 | self.top_scroll = Qt.QScrollArea() 57 | self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) 58 | self.top_scroll_layout.addWidget(self.top_scroll) 59 | self.top_scroll.setWidgetResizable(True) 60 | self.top_widget = Qt.QWidget() 61 | self.top_scroll.setWidget(self.top_widget) 62 | self.top_layout = Qt.QVBoxLayout(self.top_widget) 63 | self.top_grid_layout = Qt.QGridLayout() 64 | self.top_layout.addLayout(self.top_grid_layout) 65 | 66 | self.settings = Qt.QSettings("GNU Radio", "dcoffset_test") 67 | 68 | try: 69 | if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): 70 | self.restoreGeometry(self.settings.value("geometry").toByteArray()) 71 | else: 72 | self.restoreGeometry(self.settings.value("geometry")) 73 | except: 74 | pass 75 | 76 | ################################################## 77 | # Variables 78 | ################################################## 79 | self.samp_rate = samp_rate = 2.4e6 80 | self.real = real = -0.011900 81 | self.imag = imag = -0.004100 82 | self.gain = gain = 16 83 | self.center_freq = center_freq = 95.7e6 84 | self.amp_on = amp_on = 14 85 | 86 | ################################################## 87 | # Blocks 88 | ################################################## 89 | self._real_range = Range(-0.1, 0.1, 0.0001, -0.011900, 200) 90 | self._real_win = RangeWidget(self._real_range, self.set_real, 'real', "counter_slider", float, QtCore.Qt.Horizontal) 91 | self.top_grid_layout.addWidget(self._real_win, 1, 0, 1, 1) 92 | for r in range(1, 2): 93 | self.top_grid_layout.setRowStretch(r, 1) 94 | for c in range(0, 1): 95 | self.top_grid_layout.setColumnStretch(c, 1) 96 | self._imag_range = Range(-0.1, 0.1, 0.0001, -0.004100, 200) 97 | self._imag_win = RangeWidget(self._imag_range, self.set_imag, 'imag', "counter_slider", float, QtCore.Qt.Horizontal) 98 | self.top_grid_layout.addWidget(self._imag_win, 1, 1, 1, 1) 99 | for r in range(1, 2): 100 | self.top_grid_layout.setRowStretch(r, 1) 101 | for c in range(1, 2): 102 | self.top_grid_layout.setColumnStretch(c, 1) 103 | self._gain_range = Range(0, 40, 8, 16, 200) 104 | self._gain_win = RangeWidget(self._gain_range, self.set_gain, 'Gain', "counter_slider", float, QtCore.Qt.Horizontal) 105 | self.top_grid_layout.addWidget(self._gain_win, 0, 1, 1, 1) 106 | for r in range(0, 1): 107 | self.top_grid_layout.setRowStretch(r, 1) 108 | for c in range(1, 2): 109 | self.top_grid_layout.setColumnStretch(c, 1) 110 | self._center_freq_tool_bar = Qt.QToolBar(self) 111 | self._center_freq_tool_bar.addWidget(Qt.QLabel('Center Frequency' + ": ")) 112 | self._center_freq_line_edit = Qt.QLineEdit(str(self.center_freq)) 113 | self._center_freq_tool_bar.addWidget(self._center_freq_line_edit) 114 | self._center_freq_line_edit.returnPressed.connect( 115 | lambda: self.set_center_freq(eng_notation.str_to_num(str(self._center_freq_line_edit.text())))) 116 | self.top_grid_layout.addWidget(self._center_freq_tool_bar, 0, 0, 1, 1) 117 | for r in range(0, 1): 118 | self.top_grid_layout.setRowStretch(r, 1) 119 | for c in range(0, 1): 120 | self.top_grid_layout.setColumnStretch(c, 1) 121 | self.qtgui_time_sink_x_0 = qtgui.time_sink_c( 122 | 2048, #size 123 | samp_rate, #samp_rate 124 | "", #name 125 | 4, #number of inputs 126 | None # parent 127 | ) 128 | self.qtgui_time_sink_x_0.set_update_time(0.10) 129 | self.qtgui_time_sink_x_0.set_y_axis(-0.01, 0.01) 130 | 131 | self.qtgui_time_sink_x_0.set_y_label('Amplitude', "") 132 | 133 | self.qtgui_time_sink_x_0.enable_tags(True) 134 | self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") 135 | self.qtgui_time_sink_x_0.enable_autoscale(True) 136 | self.qtgui_time_sink_x_0.enable_grid(True) 137 | self.qtgui_time_sink_x_0.enable_axis_labels(True) 138 | self.qtgui_time_sink_x_0.enable_control_panel(False) 139 | self.qtgui_time_sink_x_0.enable_stem_plot(False) 140 | 141 | 142 | labels = ['Add Const I', 'Add Const Q', 'Manual CorrectIQ I', 'Manual CorrectIQ Q', 'Auto CorrectIQ I', 143 | 'Auto CorrectIQ Q', 'Full CorrectIQ I', 'Full CorrectIQ Q', '', ''] 144 | widths = [1, 1, 1, 1, 1, 145 | 1, 1, 1, 1, 1] 146 | colors = ['blue', 'red', 'green', 'black', 'cyan', 147 | 'magenta', 'yellow', 'dark red', 'dark green', 'dark blue'] 148 | alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 149 | 1.0, 1.0, 1.0, 1.0, 1.0] 150 | styles = [1, 1, 1, 1, 1, 151 | 1, 1, 1, 1, 1] 152 | markers = [-1, -1, -1, -1, -1, 153 | -1, -1, -1, -1, -1] 154 | 155 | 156 | for i in range(8): 157 | if len(labels[i]) == 0: 158 | if (i % 2 == 0): 159 | self.qtgui_time_sink_x_0.set_line_label(i, "Re{{Data {0}}}".format(i/2)) 160 | else: 161 | self.qtgui_time_sink_x_0.set_line_label(i, "Im{{Data {0}}}".format(i/2)) 162 | else: 163 | self.qtgui_time_sink_x_0.set_line_label(i, labels[i]) 164 | self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) 165 | self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) 166 | self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) 167 | self.qtgui_time_sink_x_0.set_line_marker(i, markers[i]) 168 | self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) 169 | 170 | self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget) 171 | self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win) 172 | self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( 173 | 2048, #size 174 | window.WIN_BLACKMAN_hARRIS, #wintype 175 | center_freq, #fc 176 | samp_rate, #bw 177 | "", #name 178 | 4, 179 | None # parent 180 | ) 181 | self.qtgui_freq_sink_x_0.set_update_time(0.10) 182 | self.qtgui_freq_sink_x_0.set_y_axis(-120, -20) 183 | self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB') 184 | self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") 185 | self.qtgui_freq_sink_x_0.enable_autoscale(False) 186 | self.qtgui_freq_sink_x_0.enable_grid(True) 187 | self.qtgui_freq_sink_x_0.set_fft_average(0.2) 188 | self.qtgui_freq_sink_x_0.enable_axis_labels(True) 189 | self.qtgui_freq_sink_x_0.enable_control_panel(False) 190 | self.qtgui_freq_sink_x_0.set_fft_window_normalized(False) 191 | 192 | 193 | 194 | labels = ['Add Const', 'Manual Offset', 'AutoSync Offset', 'CorrectIQ', '', 195 | '', '', '', '', ''] 196 | widths = [1, 1, 1, 1, 1, 197 | 1, 1, 1, 1, 1] 198 | colors = ["blue", "red", "green", "black", "cyan", 199 | "magenta", "yellow", "dark red", "dark green", "dark blue"] 200 | alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 201 | 1.0, 1.0, 1.0, 1.0, 1.0] 202 | 203 | for i in range(4): 204 | if len(labels[i]) == 0: 205 | self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i)) 206 | else: 207 | self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) 208 | self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) 209 | self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) 210 | self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) 211 | 212 | self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) 213 | self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win) 214 | self.osmosdr_source_0 = osmosdr.source( 215 | args="numchan=" + str(1) + " " + 'rtl' 216 | ) 217 | self.osmosdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t()) 218 | self.osmosdr_source_0.set_sample_rate(samp_rate) 219 | self.osmosdr_source_0.set_center_freq(center_freq, 0) 220 | self.osmosdr_source_0.set_freq_corr(0, 0) 221 | self.osmosdr_source_0.set_dc_offset_mode(0, 0) 222 | self.osmosdr_source_0.set_iq_balance_mode(0, 0) 223 | self.osmosdr_source_0.set_gain_mode(False, 0) 224 | self.osmosdr_source_0.set_gain(gain, 0) 225 | self.osmosdr_source_0.set_if_gain(0, 0) 226 | self.osmosdr_source_0.set_bb_gain(0, 0) 227 | self.osmosdr_source_0.set_antenna('', 0) 228 | self.osmosdr_source_0.set_bandwidth(0, 0) 229 | self.correctiq_correctiq_man_0 = correctiq.correctiq_man(real, imag) 230 | self.correctiq_correctiq_auto_0 = correctiq.correctiq_auto(samp_rate, center_freq, gain, 2) 231 | self.correctiq_correctiq_1 = correctiq.correctiq() 232 | self.blocks_add_const_vxx_1_0 = blocks.add_const_cc(real + 1j * imag) 233 | 234 | 235 | 236 | ################################################## 237 | # Connections 238 | ################################################## 239 | self.connect((self.blocks_add_const_vxx_1_0, 0), (self.qtgui_freq_sink_x_0, 0)) 240 | self.connect((self.blocks_add_const_vxx_1_0, 0), (self.qtgui_time_sink_x_0, 0)) 241 | self.connect((self.correctiq_correctiq_1, 0), (self.qtgui_freq_sink_x_0, 3)) 242 | self.connect((self.correctiq_correctiq_1, 0), (self.qtgui_time_sink_x_0, 3)) 243 | self.connect((self.correctiq_correctiq_auto_0, 0), (self.qtgui_freq_sink_x_0, 2)) 244 | self.connect((self.correctiq_correctiq_auto_0, 0), (self.qtgui_time_sink_x_0, 2)) 245 | self.connect((self.correctiq_correctiq_man_0, 0), (self.qtgui_freq_sink_x_0, 1)) 246 | self.connect((self.correctiq_correctiq_man_0, 0), (self.qtgui_time_sink_x_0, 1)) 247 | self.connect((self.osmosdr_source_0, 0), (self.blocks_add_const_vxx_1_0, 0)) 248 | self.connect((self.osmosdr_source_0, 0), (self.correctiq_correctiq_1, 0)) 249 | self.connect((self.osmosdr_source_0, 0), (self.correctiq_correctiq_auto_0, 0)) 250 | self.connect((self.osmosdr_source_0, 0), (self.correctiq_correctiq_man_0, 0)) 251 | 252 | 253 | def closeEvent(self, event): 254 | self.settings = Qt.QSettings("GNU Radio", "dcoffset_test") 255 | self.settings.setValue("geometry", self.saveGeometry()) 256 | event.accept() 257 | 258 | def get_samp_rate(self): 259 | return self.samp_rate 260 | 261 | def set_samp_rate(self, samp_rate): 262 | self.samp_rate = samp_rate 263 | self.osmosdr_source_0.set_sample_rate(self.samp_rate) 264 | self.qtgui_freq_sink_x_0.set_frequency_range(self.center_freq, self.samp_rate) 265 | self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate) 266 | 267 | def get_real(self): 268 | return self.real 269 | 270 | def set_real(self, real): 271 | self.real = real 272 | self.blocks_add_const_vxx_1_0.set_k(self.real + 1j * self.imag) 273 | self.correctiq_correctiq_man_0.set_real(self.real) 274 | 275 | def get_imag(self): 276 | return self.imag 277 | 278 | def set_imag(self, imag): 279 | self.imag = imag 280 | self.blocks_add_const_vxx_1_0.set_k(self.real + 1j * self.imag) 281 | self.correctiq_correctiq_man_0.set_imag(self.imag) 282 | 283 | def get_gain(self): 284 | return self.gain 285 | 286 | def set_gain(self, gain): 287 | self.gain = gain 288 | self.correctiq_correctiq_auto_0.set_gain(self.gain) 289 | self.osmosdr_source_0.set_gain(self.gain, 0) 290 | 291 | def get_center_freq(self): 292 | return self.center_freq 293 | 294 | def set_center_freq(self, center_freq): 295 | self.center_freq = center_freq 296 | Qt.QMetaObject.invokeMethod(self._center_freq_line_edit, "setText", Qt.Q_ARG("QString", eng_notation.num_to_str(self.center_freq))) 297 | self.correctiq_correctiq_auto_0.set_freq(self.center_freq) 298 | self.osmosdr_source_0.set_center_freq(self.center_freq, 0) 299 | self.qtgui_freq_sink_x_0.set_frequency_range(self.center_freq, self.samp_rate) 300 | 301 | def get_amp_on(self): 302 | return self.amp_on 303 | 304 | def set_amp_on(self, amp_on): 305 | self.amp_on = amp_on 306 | 307 | 308 | 309 | 310 | 311 | def main(top_block_cls=dcoffset_test, options=None): 312 | 313 | if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): 314 | style = gr.prefs().get_string('qtgui', 'style', 'raster') 315 | Qt.QApplication.setGraphicsSystem(style) 316 | qapp = Qt.QApplication(sys.argv) 317 | 318 | tb = top_block_cls() 319 | 320 | tb.start() 321 | 322 | tb.show() 323 | 324 | def sig_handler(sig=None, frame=None): 325 | Qt.QApplication.quit() 326 | 327 | signal.signal(signal.SIGINT, sig_handler) 328 | signal.signal(signal.SIGTERM, sig_handler) 329 | 330 | timer = Qt.QTimer() 331 | timer.start(500) 332 | timer.timeout.connect(lambda: None) 333 | 334 | def quitting(): 335 | tb.stop() 336 | tb.wait() 337 | 338 | qapp.aboutToQuit.connect(quitting) 339 | qapp.exec_() 340 | 341 | if __name__ == '__main__': 342 | main() 343 | -------------------------------------------------------------------------------- /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-correctiq 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | 21 | install(FILES 22 | correctiq_correctiq.block.yml 23 | correctiq_SwapIQ.block.yml 24 | correctiq_correctiq_man.block.yml 25 | correctiq_correctiq_auto.block.yml DESTINATION share/gnuradio/grc/blocks 26 | ) 27 | -------------------------------------------------------------------------------- /grc/correctiq_SwapIQ.block.yml: -------------------------------------------------------------------------------- 1 | id: correctiq_SwapIQ 2 | label: SwapIQ 3 | category: '[CORRECTIQ]' 4 | 5 | templates: 6 | imports: import correctiq 7 | make: correctiq.SwapIQ(${datatype.datatype}, ${datatype.datasize}) 8 | 9 | parameters: 10 | - id: datatype 11 | label: Input Type 12 | dtype: enum 13 | options: [complex, short, byte] 14 | option_attributes: 15 | datasize: [gr.sizeof_gr_complex, gr.sizeof_short, gr.sizeof_char] 16 | datatype: ['1', '2', '3'] 17 | hide: part 18 | 19 | inputs: 20 | - domain: stream 21 | dtype: ${ type } 22 | 23 | outputs: 24 | - domain: stream 25 | dtype: ${ type } 26 | 27 | documentation: |- 28 | This block will transpose the I and Q channels (Swap IQ) to correct for spectrally inverted inputs. 29 | 30 | file_format: 1 31 | -------------------------------------------------------------------------------- /grc/correctiq_correctiq.block.yml: -------------------------------------------------------------------------------- 1 | id: correctiq_correctiq 2 | label: CorrectIQ 3 | category: '[CORRECTIQ]' 4 | 5 | templates: 6 | imports: import correctiq 7 | make: correctiq.correctiq(${}) 8 | 9 | inputs: 10 | - domain: stream 11 | dtype: complex 12 | 13 | outputs: 14 | - domain: stream 15 | dtype: complex 16 | 17 | documentation: |- 18 | This block to removes that center frequency IQ DC spike just like some software and drivers do. Just drop it in your flowgraph after your 19 | radio source and you're all set. No more offset tuning to get rid of that spike, now you can use the whole bandwidth. 20 | 21 | file_format: 1 22 | -------------------------------------------------------------------------------- /grc/correctiq_correctiq_auto.block.yml: -------------------------------------------------------------------------------- 1 | id: correctiq_correctiq_auto 2 | label: CorrectIQ AutoSync Offset 3 | category: '[CORRECTIQ]' 4 | 5 | templates: 6 | imports: import correctiq 7 | make: correctiq.correctiq_auto(${samp_rate}, ${freq}, ${gain}, ${syncWindow}) 8 | callbacks: 9 | - set_freq(${freq}) 10 | - set_gain(${gain}) 11 | 12 | parameters: 13 | - id: samp_rate 14 | label: Sample Rate 15 | dtype: float 16 | default: samp_rate 17 | - id: syncWindow 18 | label: Sync Learning Period (sec) 19 | dtype: float 20 | default: '2' 21 | - id: freq 22 | label: Frequency 23 | dtype: float 24 | - id: gain 25 | label: Upstream Gain 26 | dtype: float 27 | 28 | inputs: 29 | - domain: stream 30 | dtype: complex 31 | 32 | outputs: 33 | - domain: stream 34 | dtype: complex 35 | 36 | documentation: |- 37 | This block to removes that center frequency IQ DC spike with a slight variation. It automatically calculates the offset then switches to straight DC offset mode to prevent any possible filtering after it's been tuned. However if frequency or upstream gain is changed, it must retune, so frequency and upstream gain are all taken as parameters and monitored for changes. 38 | 39 | file_format: 1 40 | -------------------------------------------------------------------------------- /grc/correctiq_correctiq_man.block.yml: -------------------------------------------------------------------------------- 1 | id: correctiq_correctiq_man 2 | label: CorrectIQ Manual Offset 3 | category: '[CORRECTIQ]' 4 | 5 | templates: 6 | imports: import correctiq 7 | make: correctiq.correctiq_man(${real}, ${imag}) 8 | callbacks: 9 | - set_real(${real}) 10 | - set_imag(${imag}) 11 | 12 | parameters: 13 | - id: real 14 | label: Real (I) 15 | dtype: float 16 | default: '0' 17 | - id: imag 18 | label: Imag (Q) 19 | dtype: float 20 | default: '0' 21 | 22 | inputs: 23 | - domain: stream 24 | dtype: complex 25 | 26 | outputs: 27 | - domain: stream 28 | dtype: complex 29 | 30 | documentation: |- 31 | This block provides a mechanism to manually provide a real and imaginary signal offset. Very similar to a complex add block, the block supports dynamic updating on the values. 32 | 33 | file_format: 1 34 | -------------------------------------------------------------------------------- /include/correctiq/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-correctiq 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | 21 | ######################################################################## 22 | # Install public header files 23 | ######################################################################## 24 | install(FILES 25 | api.h 26 | correctiq.h 27 | SwapIQ.h 28 | correctiq_man.h 29 | correctiq_auto.h DESTINATION include/correctiq 30 | ) 31 | -------------------------------------------------------------------------------- /include/correctiq/SwapIQ.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_SWAPIQ_H 22 | #define INCLUDED_CORRECTIQ_SWAPIQ_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace correctiq { 29 | 30 | /*! 31 | * \brief <+description of block+> 32 | * \ingroup correctiq 33 | * 34 | */ 35 | class CORRECTIQ_API SwapIQ : virtual public gr::sync_block 36 | { 37 | public: 38 | typedef std::shared_ptr sptr; 39 | 40 | /*! 41 | * \brief Return a shared_ptr to a new instance of correctiq::SwapIQ. 42 | * 43 | * To avoid accidental use of raw pointers, correctiq::SwapIQ's 44 | * constructor is in a private implementation 45 | * class. correctiq::SwapIQ::make is the public interface for 46 | * creating new instances. 47 | */ 48 | static sptr make(int datatype, int datasize); 49 | }; 50 | 51 | } // namespace correctiq 52 | } // namespace gr 53 | 54 | #endif /* INCLUDED_CORRECTIQ_SWAPIQ_H */ 55 | 56 | -------------------------------------------------------------------------------- /include/correctiq/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-correctiq 6 | * 7 | * GNU Radio is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation; either version 3, or (at your option) 10 | * any later version. 11 | * 12 | * GNU Radio is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with GNU Radio; see the file COPYING. If not, write to 19 | * the Free Software Foundation, Inc., 51 Franklin Street, 20 | * Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef INCLUDED_CORRECTIQ_API_H 24 | #define INCLUDED_CORRECTIQ_API_H 25 | 26 | #include 27 | 28 | #ifdef gnuradio_correctiq_EXPORTS 29 | #define CORRECTIQ_API __GR_ATTR_EXPORT 30 | #else 31 | #define CORRECTIQ_API __GR_ATTR_IMPORT 32 | #endif 33 | 34 | #endif /* INCLUDED_CORRECTIQ_API_H */ 35 | -------------------------------------------------------------------------------- /include/correctiq/correctiq.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_CORRECTIQ_H 22 | #define INCLUDED_CORRECTIQ_CORRECTIQ_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace correctiq { 29 | 30 | /*! 31 | * \brief <+description of block+> 32 | * \ingroup correctiq 33 | * 34 | */ 35 | class CORRECTIQ_API correctiq : virtual public gr::sync_block 36 | { 37 | public: 38 | typedef std::shared_ptr sptr; 39 | 40 | /*! 41 | * \brief Return a shared_ptr to a new instance of correctiq::correctiq. 42 | * 43 | * To avoid accidental use of raw pointers, correctiq::correctiq's 44 | * constructor is in a private implementation 45 | * class. correctiq::correctiq::make is the public interface for 46 | * creating new instances. 47 | */ 48 | static sptr make( ); 49 | }; 50 | 51 | } // namespace correctiq 52 | } // namespace gr 53 | 54 | #endif /* INCLUDED_CORRECTIQ_CORRECTIQ_H */ 55 | 56 | -------------------------------------------------------------------------------- /include/correctiq/correctiq_auto.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_CORRECTIQ_AUTO_H 22 | #define INCLUDED_CORRECTIQ_CORRECTIQ_AUTO_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace correctiq { 29 | 30 | /*! 31 | * \brief <+description of block+> 32 | * \ingroup correctiq 33 | * 34 | */ 35 | class CORRECTIQ_API correctiq_auto : virtual public gr::sync_block 36 | { 37 | public: 38 | typedef std::shared_ptr sptr; 39 | 40 | /*! 41 | * \brief Return a shared_ptr to a new instance of correctiq::correctiq_auto. 42 | * 43 | * To avoid accidental use of raw pointers, correctiq::correctiq_auto's 44 | * constructor is in a private implementation 45 | * class. correctiq::correctiq_auto::make is the public interface for 46 | * creating new instances. 47 | */ 48 | 49 | virtual double get_freq() = 0; 50 | virtual float get_gain() = 0; 51 | 52 | virtual void set_freq(double newValue) = 0; 53 | virtual void set_gain(float newValue) = 0; 54 | 55 | static sptr make(double samp_rate,double freq, float gain, float syncWindow); 56 | }; 57 | 58 | } // namespace correctiq 59 | } // namespace gr 60 | 61 | #endif /* INCLUDED_CORRECTIQ_CORRECTIQ_AUTO_H */ 62 | 63 | -------------------------------------------------------------------------------- /include/correctiq/correctiq_man.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_CORRECTIQ_MAN_H 22 | #define INCLUDED_CORRECTIQ_CORRECTIQ_MAN_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace correctiq { 29 | 30 | /*! 31 | * \brief <+description of block+> 32 | * \ingroup correctiq 33 | * 34 | */ 35 | class CORRECTIQ_API correctiq_man : virtual public gr::sync_block 36 | { 37 | public: 38 | typedef std::shared_ptr sptr; 39 | 40 | /*! 41 | * \brief Return a shared_ptr to a new instance of correctiq::correctiq_man. 42 | * 43 | * To avoid accidental use of raw pointers, correctiq::correctiq_man's 44 | * constructor is in a private implementation 45 | * class. correctiq::correctiq_man::make is the public interface for 46 | * creating new instances. 47 | */ 48 | 49 | virtual float get_real() = 0; 50 | virtual float get_imag() = 0; 51 | 52 | virtual void set_real(float newValue) = 0; 53 | virtual void set_imag(float newValue) = 0; 54 | 55 | static sptr make(float real,float imag); 56 | }; 57 | 58 | } // namespace correctiq 59 | } // namespace gr 60 | 61 | #endif /* INCLUDED_CORRECTIQ_CORRECTIQ_MAN_H */ 62 | 63 | -------------------------------------------------------------------------------- /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-correctiq 5 | # 6 | # GNU Radio is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3, or (at your option) 9 | # any later version. 10 | # 11 | # GNU Radio is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with GNU Radio; see the file COPYING. If not, write to 18 | # the Free Software Foundation, Inc., 51 Franklin Street, 19 | # Boston, MA 02110-1301, USA. 20 | 21 | ######################################################################## 22 | # Setup library 23 | ######################################################################## 24 | include(GrPlatform) #define LIB_SUFFIX 25 | 26 | list(APPEND correctiq_sources 27 | correctiq_impl.cc 28 | SwapIQ_impl.cc 29 | correctiq_man_impl.cc 30 | correctiq_auto_impl.cc 31 | ) 32 | 33 | set(correctiq_sources "${correctiq_sources}" PARENT_SCOPE) 34 | if(NOT correctiq_sources) 35 | MESSAGE(STATUS "No C++ sources... skipping lib/") 36 | return() 37 | endif(NOT correctiq_sources) 38 | 39 | add_library(gnuradio-correctiq SHARED ${correctiq_sources}) 40 | target_link_libraries(gnuradio-correctiq gnuradio::gnuradio-runtime) 41 | target_include_directories(gnuradio-correctiq 42 | PUBLIC $ 43 | PUBLIC $ 44 | ) 45 | set_target_properties(gnuradio-correctiq PROPERTIES DEFINE_SYMBOL "gnuradio_correctiq_EXPORTS") 46 | 47 | if(APPLE) 48 | set_target_properties(gnuradio-correctiq PROPERTIES 49 | INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" 50 | ) 51 | endif(APPLE) 52 | 53 | ######################################################################## 54 | # Install built library files 55 | ######################################################################## 56 | include(GrMiscUtils) 57 | GR_LIBRARY_FOO(gnuradio-correctiq) 58 | 59 | ######################################################################## 60 | # Print summary 61 | ######################################################################## 62 | message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") 63 | message(STATUS "Building for version: ${VERSION} / ${LIBVER}") 64 | 65 | ######################################################################## 66 | # Build and register unit test 67 | ######################################################################## 68 | include(GrTest) 69 | 70 | # If your unit tests require special include paths, add them here 71 | #include_directories() 72 | # List all files that contain Boost.UTF unit tests here 73 | list(APPEND test_correctiq_sources 74 | ) 75 | # Anything we need to link to for the unit tests go here 76 | list(APPEND GR_TEST_TARGET_DEPS gnuradio-correctiq) 77 | 78 | if(NOT test_correctiq_sources) 79 | MESSAGE(STATUS "No C++ unit tests... skipping") 80 | return() 81 | endif(NOT test_correctiq_sources) 82 | 83 | foreach(qa_file ${test_correctiq_sources}) 84 | GR_ADD_CPP_TEST("correctiq_${qa_file}" 85 | ${CMAKE_CURRENT_SOURCE_DIR}/${qa_file} 86 | ) 87 | endforeach(qa_file) 88 | -------------------------------------------------------------------------------- /lib/SwapIQ_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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 "SwapIQ_impl.h" 26 | #include 27 | 28 | namespace gr { 29 | namespace correctiq { 30 | 31 | SwapIQ::sptr SwapIQ::make(int datatype, int datasize) { 32 | return gnuradio::make_block_sptr(datatype, datasize); 33 | } 34 | 35 | /* 36 | * The private constructor 37 | */ 38 | SwapIQ_impl::SwapIQ_impl(int datatype, int datasize) 39 | : gr::sync_block("SwapIQ", gr::io_signature::make(1, 1, datasize), 40 | gr::io_signature::make(1, 1, datasize)) { 41 | d_datatype = datatype; 42 | 43 | if (d_datatype != SWAPTYPE_FLOATCOMPLEX) { 44 | gr::block::set_output_multiple(2); // Make sure we work with pairs 45 | } 46 | } 47 | 48 | /* 49 | * Our virtual destructor. 50 | */ 51 | SwapIQ_impl::~SwapIQ_impl() {} 52 | 53 | int SwapIQ_impl::work(int noutput_items, gr_vector_const_void_star &input_items, 54 | gr_vector_void_star &output_items) { 55 | // Constructor guarantees we'll have pairs. 56 | 57 | long i; 58 | long noi; 59 | 60 | switch (d_datatype) { 61 | case SWAPTYPE_FLOATCOMPLEX: { 62 | noi = noutput_items * 2; // Each complex is 2 floats 63 | const float *infloat = (const float *)input_items[0]; 64 | float *outfloat = (float *)output_items[0]; 65 | 66 | for (i = 0; i < noi; i += 2) { 67 | outfloat[i] = infloat[i + 1]; 68 | outfloat[i + 1] = infloat[i]; 69 | } 70 | } break; 71 | case SWAPTYPE_SHORTCOMPLEX: { 72 | noi = noutput_items; 73 | const int16_t *inShort = (const int16_t *)input_items[0]; 74 | int16_t *outShort = (int16_t *)output_items[0]; 75 | 76 | for (i = 0; i < noi; i += 2) { 77 | outShort[i] = inShort[i + 1]; 78 | outShort[i + 1] = inShort[i]; 79 | } 80 | } break; 81 | case SWAPTYPE_BYTECOMPLEX: { 82 | noi = noutput_items; 83 | const char *inByte = (const char *)input_items[0]; 84 | char *outByte = (char *)output_items[0]; 85 | 86 | for (i = 0; i < noi; i += 2) { 87 | outByte[i] = inByte[i + 1]; 88 | outByte[i + 1] = inByte[i]; 89 | } 90 | } break; 91 | } 92 | 93 | // Tell runtime system how many output items we produced. 94 | return noutput_items; 95 | } 96 | } /* namespace correctiq */ 97 | } /* namespace gr */ 98 | -------------------------------------------------------------------------------- /lib/SwapIQ_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_SWAPIQ_IMPL_H 22 | #define INCLUDED_CORRECTIQ_SWAPIQ_IMPL_H 23 | 24 | #include 25 | 26 | #define SWAPTYPE_FLOATCOMPLEX 1 27 | #define SWAPTYPE_SHORTCOMPLEX 2 28 | #define SWAPTYPE_BYTECOMPLEX 3 29 | 30 | namespace gr { 31 | namespace correctiq { 32 | 33 | class SwapIQ_impl : public SwapIQ { 34 | private: 35 | int d_datatype; 36 | 37 | public: 38 | SwapIQ_impl(int datatype, int datasize); 39 | ~SwapIQ_impl(); 40 | 41 | // Where all the action really happens 42 | int work(int noutput_items, gr_vector_const_void_star &input_items, 43 | gr_vector_void_star &output_items); 44 | }; 45 | 46 | } // namespace correctiq 47 | } // namespace gr 48 | 49 | #endif /* INCLUDED_CORRECTIQ_SWAPIQ_IMPL_H */ 50 | -------------------------------------------------------------------------------- /lib/clSComplex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * clSComplex.h 3 | * 4 | * Created on: Feb 9, 2017 5 | * Author: root 6 | */ 7 | 8 | #ifndef INCLUDE_CLENABLED_CLSCOMPLEX_H_ 9 | #define INCLUDE_CLENABLED_CLSCOMPLEX_H_ 10 | 11 | struct ComplexStruct { 12 | float real; 13 | float imag; 14 | }; 15 | 16 | typedef struct ComplexStruct SComplex; 17 | 18 | #endif /* INCLUDE_CLENABLED_CLSCOMPLEX_H_ */ 19 | -------------------------------------------------------------------------------- /lib/correctiq_auto_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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 "clSComplex.h" 26 | #include "correctiq_auto_impl.h" 27 | #include 28 | #include 29 | #include 30 | 31 | namespace gr { 32 | namespace correctiq { 33 | 34 | correctiq_auto::sptr correctiq_auto::make(double samp_rate, double freq, 35 | float gain, float syncWindow) { 36 | return gnuradio::make_block_sptr( 37 | samp_rate, freq, gain, syncWindow); 38 | } 39 | 40 | /* 41 | * The private constructor 42 | */ 43 | correctiq_auto_impl::correctiq_auto_impl(double samp_rate, double freq, 44 | float gain, float syncWindow) 45 | : gr::sync_block("correctiq_auto", 46 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 47 | gr::io_signature::make(1, 1, sizeof(gr_complex))) { 48 | avg_real = 0.0; 49 | avg_img = 0.0; 50 | 51 | d_samp_rate = samp_rate; 52 | d_freq = freq; 53 | d_gain = gain; 54 | d_syncWindow = syncWindow; 55 | 56 | synchronized = false; 57 | 58 | std::cout << "CorrectIQ Auto Synchronizing..." << std::endl; 59 | 60 | d_max_syncSamples = (long)(d_samp_rate * (double)syncWindow); 61 | // std::cout << "Using " << d_max_syncSamples << " samples for 62 | // synchronization" << std::endl; 63 | } 64 | 65 | /* 66 | * Our virtual destructor. 67 | */ 68 | correctiq_auto_impl::~correctiq_auto_impl() {} 69 | 70 | double correctiq_auto_impl::get_freq() { return d_freq; } 71 | 72 | float correctiq_auto_impl::get_gain() { return d_gain; } 73 | 74 | void correctiq_auto_impl::set_freq(double newValue) { 75 | std::cout << "[CorrectIQ_Auto] Auto Synchronizing..." << std::endl; 76 | d_freq = newValue; 77 | synchronized = false; 78 | syncCounter = 0; 79 | 80 | // reset counters on an unsync 81 | avg_real = 0.0; 82 | avg_img = 0.0; 83 | } 84 | 85 | void correctiq_auto_impl::set_gain(float newValue) { 86 | std::cout << "[CorrectIQ_Auto] Auto Synchronizing..." << std::endl; 87 | d_gain = newValue; 88 | synchronized = false; 89 | syncCounter = 0; 90 | 91 | // reset counters on an unsync 92 | avg_real = 0.0; 93 | avg_img = 0.0; 94 | } 95 | 96 | int correctiq_auto_impl::testCPU(int noutput_items, 97 | gr_vector_const_void_star &input_items, 98 | gr_vector_void_star &output_items) { 99 | const SComplex *in = (const SComplex *)input_items[0]; 100 | SComplex *out = (SComplex *)output_items[0]; 101 | 102 | int i; 103 | 104 | for (i = 0; i < noutput_items; i++) { 105 | out[i].real = in[i].real - avg_real; 106 | out[i].imag = in[i].imag - avg_img; 107 | } 108 | 109 | // Tell runtime system how many output items we produced. 110 | return noutput_items; 111 | } 112 | 113 | int correctiq_auto_impl::work(int noutput_items, 114 | gr_vector_const_void_star &input_items, 115 | gr_vector_void_star &output_items) { 116 | const SComplex *in = (const SComplex *)input_items[0]; 117 | SComplex *out = (SComplex *)output_items[0]; 118 | 119 | int i; 120 | 121 | for (i = 0; i < noutput_items; i++) { 122 | if (synchronized) { 123 | // out[i] = gr_complex(in[i].real() - avg_real,in[i].imag() - avg_img); 124 | // slightly faster than creating a new object 125 | out[i].real = in[i].real - avg_real; 126 | out[i].imag = in[i].imag - avg_img; 127 | } else { 128 | // Synchronizing. Behave just like normal correctiq. 129 | avg_real = ratio * (in[i].real - avg_real) + avg_real; 130 | avg_img = ratio * (in[i].imag - avg_img) + avg_img; 131 | 132 | out[i].real = in[i].real - avg_real; 133 | out[i].imag = in[i].imag - avg_img; 134 | 135 | syncCounter++; 136 | } 137 | } 138 | 139 | if (!synchronized && (syncCounter >= d_max_syncSamples)) { 140 | synchronized = true; 141 | 142 | std::cout << "CorrectIQ Auto offset now synchronized." << std::endl; 143 | std::cout << "Applying these offsets... Real:" << std::fixed 144 | << std::setw(11) << std::setprecision(6) << -avg_real 145 | << ", imag:" << -avg_img << std::endl; 146 | } 147 | 148 | return noutput_items; 149 | } 150 | } /* namespace correctiq */ 151 | } /* namespace gr */ 152 | -------------------------------------------------------------------------------- /lib/correctiq_auto_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_CORRECTIQ_AUTO_IMPL_H 22 | #define INCLUDED_CORRECTIQ_CORRECTIQ_AUTO_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace correctiq { 28 | 29 | class correctiq_auto_impl : public correctiq_auto { 30 | private: 31 | float avg_real = 0.0; 32 | float avg_img = 0.0; 33 | float ratio = 1e-05f; 34 | 35 | double d_samp_rate; 36 | double d_freq; 37 | float d_gain; 38 | float d_syncWindow; 39 | 40 | long syncCounter = 0; 41 | bool synchronized = false; 42 | 43 | long d_max_syncSamples; 44 | 45 | public: 46 | correctiq_auto_impl(double samp_rate, double freq, float gain, 47 | float syncWindow); 48 | ~correctiq_auto_impl(); 49 | 50 | void set_synchronized() { synchronized = true; }; // used for testing 51 | 52 | virtual double get_freq(); 53 | virtual float get_gain(); 54 | 55 | virtual void set_freq(double newValue); 56 | virtual void set_gain(float newValue); 57 | 58 | int testCPU(int noutput_items, gr_vector_const_void_star &input_items, 59 | gr_vector_void_star &output_items); 60 | 61 | int work(int noutput_items, gr_vector_const_void_star &input_items, 62 | gr_vector_void_star &output_items); 63 | }; 64 | 65 | } // namespace correctiq 66 | } // namespace gr 67 | 68 | #endif /* INCLUDED_CORRECTIQ_CORRECTIQ_AUTO_IMPL_H */ 69 | -------------------------------------------------------------------------------- /lib/correctiq_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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 "clSComplex.h" 26 | #include "correctiq_impl.h" 27 | #include 28 | 29 | namespace gr { 30 | namespace correctiq { 31 | 32 | correctiq::sptr correctiq::make() { 33 | return gnuradio::make_block_sptr(); 34 | } 35 | 36 | /* 37 | * The private constructor 38 | */ 39 | correctiq_impl::correctiq_impl() 40 | : gr::sync_block("correctiq", 41 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 42 | gr::io_signature::make(1, 1, sizeof(gr_complex))) { 43 | avg_real = 0.0; 44 | avg_img = 0.0; 45 | } 46 | 47 | /* 48 | * Our virtual destructor. 49 | */ 50 | correctiq_impl::~correctiq_impl() {} 51 | 52 | int correctiq_impl::testCPU(int noutput_items, 53 | gr_vector_const_void_star &input_items, 54 | gr_vector_void_star &output_items) { 55 | const SComplex *in = (const SComplex *)input_items[0]; 56 | SComplex *out = (SComplex *)output_items[0]; 57 | 58 | int i; 59 | 60 | for (i = 0; i < noutput_items; i++) { 61 | avg_real = ratio * (in[i].real - avg_real) + avg_real; 62 | avg_img = ratio * (in[i].imag - avg_img) + avg_img; 63 | 64 | // out[i] = gr_complex(in[i].real() - avg_real,in[i].imag() - avg_img); 65 | // slightly faster than creating a new object 66 | out[i].real = in[i].real - avg_real; 67 | out[i].imag = in[i].imag - avg_img; 68 | } 69 | 70 | // Tell runtime system how many output items we produced. 71 | return noutput_items; 72 | } 73 | 74 | int correctiq_impl::work(int noutput_items, 75 | gr_vector_const_void_star &input_items, 76 | gr_vector_void_star &output_items) { 77 | const SComplex *in = (const SComplex *)input_items[0]; 78 | SComplex *out = (SComplex *)output_items[0]; 79 | 80 | int i; 81 | 82 | for (i = 0; i < noutput_items; i++) { 83 | avg_real = ratio * (in[i].real - avg_real) + avg_real; 84 | avg_img = ratio * (in[i].imag - avg_img) + avg_img; 85 | 86 | // out[i] = gr_complex(in[i].real() - avg_real,in[i].imag() - avg_img); 87 | // slightly faster than creating a new object 88 | out[i].real = in[i].real - avg_real; 89 | out[i].imag = in[i].imag - avg_img; 90 | } 91 | 92 | // Tell runtime system how many output items we produced. 93 | return noutput_items; 94 | } 95 | } /* namespace correctiq */ 96 | } /* namespace gr */ 97 | -------------------------------------------------------------------------------- /lib/correctiq_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_CORRECTIQ_IMPL_H 22 | #define INCLUDED_CORRECTIQ_CORRECTIQ_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace correctiq { 28 | 29 | class correctiq_impl : public correctiq { 30 | private: 31 | float avg_real = 0.0; 32 | float avg_img = 0.0; 33 | float ratio = 1e-05f; 34 | 35 | public: 36 | correctiq_impl(); 37 | ~correctiq_impl(); 38 | 39 | int testCPU(int noutput_items, gr_vector_const_void_star &input_items, 40 | gr_vector_void_star &output_items); 41 | 42 | // Where all the action really happens 43 | int work(int noutput_items, gr_vector_const_void_star &input_items, 44 | gr_vector_void_star &output_items); 45 | }; 46 | 47 | } // namespace correctiq 48 | } // namespace gr 49 | 50 | #endif /* INCLUDED_CORRECTIQ_CORRECTIQ_IMPL_H */ 51 | -------------------------------------------------------------------------------- /lib/correctiq_man_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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 | #include "clSComplex.h" 22 | #include "correctiq_man_impl.h" 23 | #include 24 | 25 | namespace gr { 26 | namespace correctiq { 27 | 28 | correctiq_man::sptr correctiq_man::make(float real, float imag) { 29 | return gnuradio::make_block_sptr(real, imag); 30 | } 31 | 32 | /* 33 | * The private constructor 34 | */ 35 | correctiq_man_impl::correctiq_man_impl(float real, float imag) 36 | : gr::sync_block("correctiq_man", 37 | gr::io_signature::make(1, 1, sizeof(gr_complex)), 38 | gr::io_signature::make(1, 1, sizeof(gr_complex))) { 39 | avg_real = real; 40 | avg_img = imag; 41 | d_k = gr_complex(avg_real, avg_img); 42 | } 43 | 44 | /* 45 | * Our virtual destructor. 46 | */ 47 | correctiq_man_impl::~correctiq_man_impl() {} 48 | 49 | float correctiq_man_impl::get_real() { return avg_real; } 50 | float correctiq_man_impl::get_imag() { return avg_img; } 51 | 52 | void correctiq_man_impl::set_real(float newValue) { 53 | avg_real = newValue; 54 | d_k = gr_complex(avg_real, avg_img); 55 | } 56 | 57 | void correctiq_man_impl::set_imag(float newValue) { 58 | avg_img = newValue; 59 | d_k = gr_complex(avg_real, avg_img); 60 | } 61 | 62 | int correctiq_man_impl::testCPU(int noutput_items, 63 | gr_vector_const_void_star &input_items, 64 | gr_vector_void_star &output_items) { 65 | const SComplex *in = (const SComplex *)input_items[0]; 66 | SComplex *out = (SComplex *)output_items[0]; 67 | // const gr_complex *in = (const gr_complex *) input_items[0]; 68 | // gr_complex *out = (gr_complex *) output_items[0]; 69 | 70 | int i; 71 | 72 | // gr_complex k(avg_real,avg_img); 73 | 74 | for (i = 0; i < noutput_items; i++) { 75 | // out[i] = in[i] + k; 76 | 77 | // out[i] = gr_complex(in[i].real() - avg_real,in[i].imag() - avg_img); 78 | // slightly faster than creating a new object 79 | out[i].real = in[i].real + avg_real; 80 | out[i].imag = in[i].imag + avg_img; 81 | } 82 | 83 | // Tell runtime system how many output items we produced. 84 | return noutput_items; 85 | } 86 | 87 | int correctiq_man_impl::work(int noutput_items, 88 | gr_vector_const_void_star &input_items, 89 | gr_vector_void_star &output_items) { 90 | const SComplex *in = (const SComplex *)input_items[0]; 91 | SComplex *out = (SComplex *)output_items[0]; 92 | // const gr_complex *in = (const gr_complex *) input_items[0]; 93 | // gr_complex *out = (gr_complex *) output_items[0]; 94 | 95 | int i; 96 | 97 | // gr_complex k(avg_real,avg_img); 98 | 99 | for (i = 0; i < noutput_items; i++) { 100 | // out[i] = in[i] + k; 101 | 102 | // out[i] = gr_complex(in[i].real() - avg_real,in[i].imag() - avg_img); 103 | // slightly faster than creating a new object 104 | out[i].real = in[i].real + avg_real; 105 | out[i].imag = in[i].imag + avg_img; 106 | } 107 | 108 | // Tell runtime system how many output items we produced. 109 | return noutput_items; 110 | } 111 | } /* namespace correctiq */ 112 | } /* namespace gr */ 113 | -------------------------------------------------------------------------------- /lib/correctiq_man_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2019 ghostop14. 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_CORRECTIQ_CORRECTIQ_MAN_IMPL_H 22 | #define INCLUDED_CORRECTIQ_CORRECTIQ_MAN_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace correctiq { 28 | 29 | class correctiq_man_impl : public correctiq_man { 30 | private: 31 | float avg_real = 0.0; 32 | float avg_img = 0.0; 33 | 34 | gr_complex d_k; 35 | 36 | public: 37 | correctiq_man_impl(float real, float imag); 38 | ~correctiq_man_impl(); 39 | 40 | virtual float get_real(); 41 | virtual float get_imag(); 42 | 43 | virtual void set_real(float newValue); 44 | virtual void set_imag(float newValue); 45 | 46 | int testCPU(int noutput_items, gr_vector_const_void_star &input_items, 47 | gr_vector_void_star &output_items); 48 | 49 | int work(int noutput_items, gr_vector_const_void_star &input_items, 50 | gr_vector_void_star &output_items); 51 | }; 52 | 53 | } // namespace correctiq 54 | } // namespace gr 55 | 56 | #endif /* INCLUDED_CORRECTIQ_CORRECTIQ_MAN_IMPL_H */ 57 | -------------------------------------------------------------------------------- /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-correctiq 5 | # 6 | # SPDX-License-Identifier: GPL-3.0-or-later 7 | # 8 | 9 | ######################################################################## 10 | # Include python install macros 11 | ######################################################################## 12 | include(GrPython) 13 | if(NOT PYTHONINTERP_FOUND) 14 | return() 15 | endif() 16 | 17 | add_subdirectory(bindings) 18 | 19 | ######################################################################## 20 | # Install python sources 21 | ######################################################################## 22 | GR_PYTHON_INSTALL( 23 | FILES 24 | __init__.py 25 | DESTINATION ${GR_PYTHON_DIR}/correctiq 26 | ) 27 | 28 | ######################################################################## 29 | # Handle the unit tests 30 | ######################################################################## 31 | include(GrTest) 32 | 33 | set(GR_TEST_TARGET_DEPS gnuradio-correctiq) 34 | -------------------------------------------------------------------------------- /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 CORRECTIQ module. Place your Python package 11 | description here (python/__init__.py). 12 | ''' 13 | import os 14 | 15 | # import pybind11 generated symbols into the correctiq namespace 16 | try: 17 | # this might fail if the module is python-only 18 | from .correctiq_python import * 19 | except ModuleNotFoundError: 20 | pass 21 | 22 | # import any pure python here 23 | # 24 | -------------------------------------------------------------------------------- /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 correctiq_sources) 12 | MESSAGE(STATUS "No C++ sources... skipping python bindings") 13 | return() 14 | endif(NOT correctiq_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 correctiq_python_files 32 | correctiq_python.cc 33 | correctiq_man_python.cc 34 | correctiq_auto_python.cc 35 | SwapIQ_python.cc python_bindings.cc) 36 | 37 | GR_PYBIND_MAKE_OOT(correctiq 38 | ../.. 39 | gr::correctiq 40 | "${correctiq_python_files}") 41 | 42 | install(TARGETS correctiq_python DESTINATION ${GR_PYTHON_DIR}/correctiq COMPONENT pythonapi) 43 | -------------------------------------------------------------------------------- /python/bindings/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghostop14/gr-correctiq/f1189bf9f1b4e27daa0c1fe69c6464a39cdf51c5/python/bindings/README.md -------------------------------------------------------------------------------- /python/bindings/SwapIQ_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(SwapIQ.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(38a3f44a9f24c287566dc0c6dbd011e1) */ 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_SwapIQ(py::module& m) 31 | { 32 | 33 | using SwapIQ = ::gr::correctiq::SwapIQ; 34 | 35 | 36 | py::class_>(m, "SwapIQ", D(SwapIQ)) 38 | 39 | .def(py::init(&SwapIQ::make), 40 | py::arg("datatype"), 41 | py::arg("datasize"), 42 | D(SwapIQ,make) 43 | ) 44 | 45 | 46 | 47 | 48 | ; 49 | 50 | 51 | 52 | 53 | } 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /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/correctiq_auto_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(correctiq_auto.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(019fe014e1a0b11108cc8c5984d9fe23) */ 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_correctiq_auto(py::module& m) 31 | { 32 | 33 | using correctiq_auto = ::gr::correctiq::correctiq_auto; 34 | 35 | 36 | py::class_>(m, "correctiq_auto", D(correctiq_auto)) 38 | 39 | .def(py::init(&correctiq_auto::make), 40 | py::arg("samp_rate"), 41 | py::arg("freq"), 42 | py::arg("gain"), 43 | py::arg("syncWindow"), 44 | D(correctiq_auto,make) 45 | ) 46 | 47 | 48 | 49 | 50 | .def("get_freq",&correctiq_auto::get_freq, 51 | D(correctiq_auto,get_freq) 52 | ) 53 | 54 | 55 | 56 | .def("get_gain",&correctiq_auto::get_gain, 57 | D(correctiq_auto,get_gain) 58 | ) 59 | 60 | 61 | 62 | .def("set_freq",&correctiq_auto::set_freq, 63 | py::arg("newValue"), 64 | D(correctiq_auto,set_freq) 65 | ) 66 | 67 | 68 | 69 | .def("set_gain",&correctiq_auto::set_gain, 70 | py::arg("newValue"), 71 | D(correctiq_auto,set_gain) 72 | ) 73 | 74 | 75 | 76 | ; 77 | 78 | 79 | 80 | 81 | } 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /python/bindings/correctiq_man_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(correctiq_man.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(2169edbbd6349b9f4a17fc4c7c382a36) */ 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_correctiq_man(py::module& m) 31 | { 32 | 33 | using correctiq_man = ::gr::correctiq::correctiq_man; 34 | 35 | 36 | py::class_>(m, "correctiq_man", D(correctiq_man)) 38 | 39 | .def(py::init(&correctiq_man::make), 40 | py::arg("real"), 41 | py::arg("imag"), 42 | D(correctiq_man,make) 43 | ) 44 | 45 | 46 | 47 | 48 | .def("get_real",&correctiq_man::get_real, 49 | D(correctiq_man,get_real) 50 | ) 51 | 52 | 53 | 54 | .def("get_imag",&correctiq_man::get_imag, 55 | D(correctiq_man,get_imag) 56 | ) 57 | 58 | 59 | 60 | .def("set_real",&correctiq_man::set_real, 61 | py::arg("newValue"), 62 | D(correctiq_man,set_real) 63 | ) 64 | 65 | 66 | 67 | .def("set_imag",&correctiq_man::set_imag, 68 | py::arg("newValue"), 69 | D(correctiq_man,set_imag) 70 | ) 71 | 72 | 73 | 74 | ; 75 | 76 | 77 | 78 | 79 | } 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /python/bindings/correctiq_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(correctiq.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(bd2c83d1f9e31c5e9775d435e21a01c1) */ 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_correctiq(py::module& m) 31 | { 32 | 33 | using correctiq = ::gr::correctiq::correctiq; 34 | 35 | 36 | py::class_>(m, "correctiq", D(correctiq)) 38 | 39 | .def(py::init(&correctiq::make), 40 | D(correctiq,make) 41 | ) 42 | 43 | 44 | 45 | 46 | ; 47 | 48 | 49 | 50 | 51 | } 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /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/SwapIQ_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,correctiq, __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_correctiq_SwapIQ = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_correctiq_SwapIQ_SwapIQ = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_correctiq_SwapIQ_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/correctiq_auto_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,correctiq, __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_correctiq_correctiq_auto = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_correctiq_correctiq_auto_correctiq_auto_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_correctiq_correctiq_auto_correctiq_auto_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_correctiq_correctiq_auto_get_freq = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_correctiq_correctiq_auto_get_gain = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_correctiq_correctiq_auto_set_freq = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_correctiq_correctiq_auto_set_gain = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_correctiq_correctiq_auto_make = R"doc()doc"; 41 | 42 | 43 | -------------------------------------------------------------------------------- /python/bindings/docstrings/correctiq_man_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,correctiq, __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_correctiq_correctiq_man = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_correctiq_correctiq_man_correctiq_man_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_correctiq_correctiq_man_correctiq_man_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_correctiq_correctiq_man_get_real = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_correctiq_correctiq_man_get_imag = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_correctiq_correctiq_man_set_real = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_correctiq_correctiq_man_set_imag = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_correctiq_correctiq_man_make = R"doc()doc"; 41 | 42 | 43 | -------------------------------------------------------------------------------- /python/bindings/docstrings/correctiq_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,correctiq, __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_correctiq_correctiq = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_correctiq_correctiq_correctiq = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_correctiq_correctiq_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /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/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_correctiq(py::module& m); 25 | void bind_correctiq_man(py::module& m); 26 | void bind_correctiq_auto(py::module& m); 27 | void bind_SwapIQ(py::module& m); 28 | // ) END BINDING_FUNCTION_PROTOTYPES 29 | 30 | 31 | // We need this hack because import_array() returns NULL 32 | // for newer Python versions. 33 | // This function is also necessary because it ensures access to the C API 34 | // and removes a warning. 35 | void* init_numpy() 36 | { 37 | import_array(); 38 | return NULL; 39 | } 40 | 41 | PYBIND11_MODULE(correctiq_python, m) 42 | { 43 | // Initialize the numpy C API 44 | // (otherwise we will see segmentation faults) 45 | init_numpy(); 46 | 47 | // Allow access to base block methods 48 | py::module::import("gnuradio.gr"); 49 | 50 | /**************************************/ 51 | /* The following comment block is used for 52 | /* gr_modtool to insert binding function calls 53 | /* Please do not delete 54 | /**************************************/ 55 | // BINDING_FUNCTION_CALLS( 56 | bind_correctiq(m); 57 | bind_correctiq_man(m); 58 | bind_correctiq_auto(m); 59 | bind_SwapIQ(m); 60 | // ) END BINDING_FUNCTION_CALLS 61 | } --------------------------------------------------------------------------------