├── python ├── bindings │ ├── README.md │ ├── docstrings │ │ ├── README.md │ │ ├── nlog10volk_pydoc_template.h │ │ ├── CC2F2ByteVector_pydoc_template.h │ │ ├── quad_demod_volk_pydoc_template.h │ │ ├── costas2_pydoc_template.h │ │ ├── costas4_pydoc_template.h │ │ ├── MTFIRFilterFF_pydoc_template.h │ │ ├── MTFIRFilterCCC_pydoc_template.h │ │ ├── MTFIRFilterCCF_pydoc_template.h │ │ ├── agc_fast_pydoc_template.h │ │ └── agc_fast_ff_pydoc_template.h │ ├── CMakeLists.txt │ ├── nlog10volk_python.cc │ ├── quad_demod_volk_python.cc │ ├── CC2F2ByteVector_python.cc │ ├── costas2_python.cc │ ├── costas4_python.cc │ ├── MTFIRFilterFF_python.cc │ ├── MTFIRFilterCCC_python.cc │ ├── MTFIRFilterCCF_python.cc │ ├── bind_oot_file.py │ ├── python_bindings.cc │ ├── header_utils.py │ ├── agc_fast_ff_python.cc │ └── agc_fast_python.cc ├── __init__.py └── CMakeLists.txt ├── docs ├── doxygen │ ├── other │ │ ├── group_defs.dox │ │ └── main_page.dox │ ├── doxyxml │ │ ├── generated │ │ │ ├── __init__.py │ │ │ └── index.py │ │ ├── text.py │ │ ├── __init__.py │ │ ├── base.py │ │ └── doxyindex.py │ ├── pydoc_macros.h │ ├── CMakeLists.txt │ └── swig_doc.py ├── README.lfast └── CMakeLists.txt ├── lib ├── dt_datatypes.h ├── clSComplex.h ├── scomplex.h ├── costas2_impl.h ├── agc_fast_impl.h ├── costas4_impl.h ├── CC2F2ByteVector_impl.h ├── agc_fast_ff_impl.h ├── agc_fast_ff_impl.cc ├── CMakeLists.txt ├── agc_fast_impl.cc ├── CC2F2ByteVector_impl.cc └── fir_filter_lfast.h ├── grc ├── lfast_quad_demod_volk.block.yml ├── lfast_costas2.block.yml ├── lfast_costas4.block.yml ├── lfast_nlog10volk.block.yml ├── lfast_CC2F2ByteVector.block.yml ├── lfast_agc_fast.block.yml ├── lfast_agc_fast_ff.block.yml ├── lfast_freq_shift.block.yml ├── lfast_MTFIRFilterXX.block.yml ├── CMakeLists.txt ├── lfast_root_raised_cosine_filter.block.yml ├── lfast_MTFIRLowPassFilterXX.block.yml ├── lfast_high_pass_filter.block.yml └── lfast_low_pass_filter.block.yml ├── MANIFEST.md ├── cmake ├── Modules │ ├── lfastConfig.cmake │ ├── targetConfig.cmake.in │ └── CMakeParseArgumentsCopy.cmake └── cmake_uninstall.cmake.in ├── apps └── CMakeLists.txt ├── include └── lfast │ ├── api.h │ ├── CMakeLists.txt │ ├── CC2F2ByteVector.h │ ├── costas2.h │ ├── costas4.h │ ├── agc_fast_ff.h │ ├── agc_fast.h │ └── agc.h ├── examples ├── lfast_Test-Filter.grc ├── lfast_Test-Filter-decimating.grc └── rotator_test.grc ├── README.md └── CMakeLists.txt /python/bindings/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /python/bindings/docstrings/README.md: -------------------------------------------------------------------------------- 1 | This directory stores templates for docstrings that are scraped from the include header files for each block -------------------------------------------------------------------------------- /docs/doxygen/other/group_defs.dox: -------------------------------------------------------------------------------- 1 | /*! 2 | * \defgroup block GNU Radio LFAST C++ Signal Processing Blocks 3 | * \brief All C++ blocks that can be used from the LFAST GNU Radio 4 | * module are listed here or in the subcategories below. 5 | * 6 | */ 7 | 8 | -------------------------------------------------------------------------------- /docs/doxygen/doxyxml/generated/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Contains generated files produced by generateDS.py. 3 | 4 | These do the real work of parsing the doxygen xml files but the 5 | resultant classes are not very friendly to navigate so the rest of the 6 | doxyxml module processes them further. 7 | """ 8 | -------------------------------------------------------------------------------- /docs/doxygen/other/main_page.dox: -------------------------------------------------------------------------------- 1 | /*! \mainpage 2 | 3 | Welcome to the GNU Radio LFAST Block 4 | 5 | This is the intro page for the Doxygen manual generated for the LFAST 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 | -------------------------------------------------------------------------------- /lib/dt_datatypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dt_datatypes.h 3 | * 4 | * Created on: Apr 5, 2017 5 | * Author: mpiscopo 6 | */ 7 | 8 | #ifndef LIB_DT_DATATYPES_H_ 9 | #define LIB_DT_DATATYPES_H_ 10 | 11 | 12 | #define DTYPE_COMPLEX 1 13 | #define DTYPE_FLOAT 2 14 | #define DTYPE_INT 3 15 | #define DTYPE_CHAR 4 16 | 17 | #endif /* LIB_DT_DATATYPES_H_ */ 18 | -------------------------------------------------------------------------------- /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 | 12 | struct ComplexStruct { 13 | float real; 14 | float imag; 15 | }; 16 | 17 | typedef struct ComplexStruct SComplex; 18 | 19 | #endif /* INCLUDE_CLENABLED_CLSCOMPLEX_H_ */ 20 | -------------------------------------------------------------------------------- /docs/README.lfast: -------------------------------------------------------------------------------- 1 | This is the lfast-write-a-block package meant as a guide to building 2 | out-of-tree packages. To use the lfast blocks, the Python namespaces 3 | is in 'lfast', which is imported as: 4 | 5 | import lfast 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(lfast) 12 | -------------------------------------------------------------------------------- /grc/lfast_quad_demod_volk.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_quad_demod_volk 4 | label: Quadrature Demod Volk 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: gain 9 | label: Gain 10 | dtype: real 11 | default: samp_rate/(2*math.pi*fsk_deviation_hz/8.0) 12 | 13 | inputs: 14 | - domain: stream 15 | dtype: complex 16 | 17 | outputs: 18 | - domain: stream 19 | dtype: float 20 | 21 | templates: 22 | imports: import lfast 23 | make: lfast.quad_demod_volk(${gain}) 24 | callbacks: 25 | - set_gain(${gain}) 26 | 27 | file_format: 1 28 | -------------------------------------------------------------------------------- /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 LFAST module. Place your Python package 11 | description here (python/__init__.py). 12 | ''' 13 | import os 14 | 15 | # import pybind11 generated symbols into the lfast namespace 16 | try: 17 | # this might fail if the module is python-only 18 | from .lfast_python import * 19 | except ModuleNotFoundError: 20 | pass 21 | 22 | # import any pure python here 23 | # 24 | -------------------------------------------------------------------------------- /lib/scomplex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * scomplex.h 3 | * 4 | * Author: ghostop14 5 | */ 6 | 7 | #ifndef LIB_SCOMPLEX_H_ 8 | #define LIB_SCOMPLEX_H_ 9 | 10 | #include 11 | #include 12 | 13 | // Common type definitions 14 | typedef std::complex SComplex; 15 | typedef std::vector > ComplexVector; 16 | 17 | // This structure version is used in some places for optimization to get direct access 18 | // to the values without having to make function calls to get/set. 19 | struct ComplexStruct { 20 | float real; 21 | float imag; 22 | }; 23 | 24 | typedef struct ComplexStruct StructComplex; 25 | 26 | #endif /* LIB_SCOMPLEX_H_ */ 27 | -------------------------------------------------------------------------------- /MANIFEST.md: -------------------------------------------------------------------------------- 1 | title: The LFAST OOT Module 2 | brief: Short description of gr-lfast 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-lfast. 15 | You may use some *basic* Markdown here. 16 | If left empty, it will try to find a README file instead. 17 | -------------------------------------------------------------------------------- /python/bindings/docstrings/nlog10volk_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_nlog10volk = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_nlog10volk_nlog10volk = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_nlog10volk_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/CC2F2ByteVector_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_CC2F2ByteVector = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_CC2F2ByteVector_CC2F2ByteVector = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_CC2F2ByteVector_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /python/bindings/docstrings/quad_demod_volk_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_quad_demod_volk = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_quad_demod_volk_quad_demod_volk = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_quad_demod_volk_make = R"doc()doc"; 26 | 27 | 28 | -------------------------------------------------------------------------------- /grc/lfast_costas2.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_costas2 4 | label: Accel Costas 2nd Order Loop 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: w 9 | label: Loop Bandwidth 10 | dtype: real 11 | - id: genSignalPDUs 12 | label: Gen Signal PDUs 13 | dtype: enum 14 | options: ['False', 'True'] 15 | option_labels: ['Off', 'On'] 16 | 17 | inputs: 18 | - domain: stream 19 | dtype: complex 20 | - domain: message 21 | id: msgin 22 | optional: true 23 | 24 | outputs: 25 | - domain: stream 26 | dtype: complex 27 | - domain: message 28 | id: msgout 29 | optional: true 30 | 31 | templates: 32 | imports: import lfast 33 | make: lfast.costas2(${w}, 2, ${genSignalPDUs}) 34 | callbacks: 35 | - set_loop_bandwidth(${w}) 36 | 37 | file_format: 1 38 | -------------------------------------------------------------------------------- /grc/lfast_costas4.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_costas4 4 | label: Accel Costas 4th Order Loop 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: w 9 | label: Loop Bandwidth 10 | dtype: real 11 | - id: genSignalPDUs 12 | label: Gen Signal PDUs 13 | dtype: enum 14 | options: ['False', 'True'] 15 | option_labels: ['Off', 'On'] 16 | 17 | inputs: 18 | - domain: stream 19 | dtype: complex 20 | - domain: message 21 | id: msgin 22 | optional: true 23 | 24 | outputs: 25 | - domain: stream 26 | dtype: complex 27 | - domain: message 28 | id: msgout 29 | optional: true 30 | 31 | templates: 32 | imports: import lfast 33 | make: lfast.costas4(${w}, 4, ${genSignalPDUs}) 34 | callbacks: 35 | - set_loop_bandwidth(${w}) 36 | 37 | file_format: 1 38 | -------------------------------------------------------------------------------- /grc/lfast_nlog10volk.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_nlog10volk 4 | label: Log10 Volk 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: n 9 | label: n 10 | dtype: real 11 | default: '1' 12 | hide: ${ 'part' if vlen == 1 else 'none' } 13 | - id: k 14 | label: k 15 | dtype: real 16 | default: '0' 17 | - id: vlen 18 | label: Vec Length 19 | dtype: int 20 | default: '1' 21 | hide: ${ 'part' if vlen == 1 else 'none' } 22 | 23 | inputs: 24 | - domain: stream 25 | dtype: float 26 | vlen: ${ vlen } 27 | 28 | outputs: 29 | - domain: stream 30 | dtype: float 31 | vlen: ${ vlen } 32 | asserts: 33 | - ${ vlen >= 1 } 34 | 35 | templates: 36 | imports: import lfast 37 | make: lfast.nlog10volk(${n}, ${vlen}, ${k}) 38 | 39 | file_format: 1 40 | -------------------------------------------------------------------------------- /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/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-lfast 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 | -------------------------------------------------------------------------------- /python/bindings/docstrings/costas2_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_costas2 = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_costas2_costas2_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_costas2_costas2_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_costas2_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_costas2_error = R"doc()doc"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /python/bindings/docstrings/costas4_pydoc_template.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_costas4 = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_costas4_costas4_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_costas4_costas4_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_costas4_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_costas4_error = R"doc()doc"; 32 | 33 | 34 | -------------------------------------------------------------------------------- /cmake/Modules/lfastConfig.cmake: -------------------------------------------------------------------------------- 1 | INCLUDE(FindPkgConfig) 2 | PKG_CHECK_MODULES(PC_LFAST lfast) 3 | 4 | FIND_PATH( 5 | LFAST_INCLUDE_DIRS 6 | NAMES lfast/api.h 7 | HINTS $ENV{LFAST_DIR}/include 8 | ${PC_LFAST_INCLUDEDIR} 9 | PATHS ${CMAKE_INSTALL_PREFIX}/include 10 | /usr/local/include 11 | /usr/include 12 | ) 13 | 14 | FIND_LIBRARY( 15 | LFAST_LIBRARIES 16 | NAMES gnuradio-lfast 17 | HINTS $ENV{LFAST_DIR}/lib 18 | ${PC_LFAST_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}/lfastTarget.cmake") 28 | 29 | INCLUDE(FindPackageHandleStandardArgs) 30 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(LFAST DEFAULT_MSG LFAST_LIBRARIES LFAST_INCLUDE_DIRS) 31 | MARK_AS_ADVANCED(LFAST_LIBRARIES LFAST_INCLUDE_DIRS) 32 | -------------------------------------------------------------------------------- /grc/lfast_CC2F2ByteVector.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_CC2F2ByteVector 4 | label: Accel Complex2Real2Byte2Vector 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: scale 9 | label: Scale 10 | dtype: int 11 | default: '1' 12 | - id: vecLength 13 | label: Vector length 14 | dtype: int 15 | default: '1' 16 | hide: ${ 'part' if vecLength == 1 else 'none' } 17 | - id: num_items 18 | label: Num Items 19 | dtype: int 20 | default: '2' 21 | hide: ${ 'part' if vecLength == 1 else 'none' } 22 | 23 | inputs: 24 | - domain: stream 25 | dtype: complex 26 | vlen: ${ vecLength } 27 | 28 | outputs: 29 | - domain: stream 30 | dtype: byte 31 | vlen: ${ vecLength*num_items } 32 | asserts: 33 | - ${ num_items > 0 } 34 | - ${ vecLength >= 1 } 35 | 36 | templates: 37 | imports: import lfast 38 | make: lfast.CC2F2ByteVector(${scale}, ${vecLength}, ${num_items}) 39 | 40 | file_format: 1 41 | -------------------------------------------------------------------------------- /grc/lfast_agc_fast.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_agc_fast 4 | label: Accel AGC 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: rate 9 | label: Rate 10 | dtype: real 11 | default: 1e-4 12 | - id: reference 13 | label: Reference 14 | dtype: real 15 | default: '1.0' 16 | - id: gain 17 | label: Gain 18 | dtype: real 19 | default: '1.0' 20 | - id: max_gain 21 | label: Max Gain 22 | dtype: real 23 | default: '65536' 24 | 25 | inputs: 26 | - domain: stream 27 | dtype: complex 28 | 29 | outputs: 30 | - domain: stream 31 | dtype: complex 32 | 33 | templates: 34 | imports: import lfast 35 | make: |- 36 | lfast.agc_fast(${rate}, ${reference}, ${gain}) 37 | self.${id}.set_max_gain(${max_gain}) 38 | callbacks: 39 | - set_rate(${rate}) 40 | - set_reference(${reference}) 41 | - set_gain(${gain}) 42 | - set_max_gain(${max_gain}) 43 | 44 | file_format: 1 45 | -------------------------------------------------------------------------------- /grc/lfast_agc_fast_ff.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_agc_fast_ff 4 | label: Accel AGC Float 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: rate 9 | label: Rate 10 | dtype: real 11 | default: 1e-4 12 | - id: reference 13 | label: Reference 14 | dtype: real 15 | default: '1.0' 16 | - id: gain 17 | label: Gain 18 | dtype: real 19 | default: '1.0' 20 | - id: max_gain 21 | label: Max Gain 22 | dtype: real 23 | default: '65536' 24 | 25 | inputs: 26 | - domain: stream 27 | dtype: float 28 | 29 | outputs: 30 | - domain: stream 31 | dtype: float 32 | 33 | templates: 34 | imports: import lfast 35 | make: |- 36 | lfast.agc_fast_ff(${rate}, ${reference}, ${gain}) 37 | self.${id}.set_max_gain(${max_gain}) 38 | callbacks: 39 | - set_rate(${rate}) 40 | - set_reference(${reference}) 41 | - set_gain(${gain}) 42 | - set_max_gain(${max_gain}) 43 | 44 | file_format: 1 45 | -------------------------------------------------------------------------------- /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-lfast 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 | -------------------------------------------------------------------------------- /grc/lfast_freq_shift.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_freq_shift 4 | label: Freq Shift 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: sample_rate 9 | label: Sample Rate 10 | dtype: real 11 | default: samp_rate 12 | - id: freq 13 | label: Frequency Shift 14 | dtype: real 15 | default: '0.0' 16 | 17 | inputs: 18 | - domain: stream 19 | dtype: complex 20 | 21 | outputs: 22 | - domain: stream 23 | dtype: complex 24 | 25 | templates: 26 | imports: |- 27 | from gnuradio import blocks 28 | import math 29 | make: blocks.rotator_cc(2.0*math.pi*${freq}/${sample_rate}) 30 | callbacks: 31 | - set_phase_inc(2.0*math.pi*${freq}/${sample_rate}) 32 | 33 | documentation: |- 34 | This block is a convenience wrapper around using a rotator block for frequency shifting. This block obfuscates the 2*Pi*freq/samp_rate phase_inc field and calculation, and only requires the designer to provide the frequency and sample rate. 35 | 36 | file_format: 1 37 | -------------------------------------------------------------------------------- /python/bindings/docstrings/MTFIRFilterFF_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_MTFIRFilterFF = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_MTFIRFilterFF_MTFIRFilterFF_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_MTFIRFilterFF_MTFIRFilterFF_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_MTFIRFilterFF_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_MTFIRFilterFF_set_taps = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_lfast_MTFIRFilterFF_taps = R"doc()doc"; 35 | 36 | 37 | -------------------------------------------------------------------------------- /python/bindings/docstrings/MTFIRFilterCCC_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_MTFIRFilterCCC = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_MTFIRFilterCCC_MTFIRFilterCCC_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_MTFIRFilterCCC_MTFIRFilterCCC_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_MTFIRFilterCCC_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_MTFIRFilterCCC_set_taps = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_lfast_MTFIRFilterCCC_taps = R"doc()doc"; 35 | 36 | 37 | -------------------------------------------------------------------------------- /python/bindings/docstrings/MTFIRFilterCCF_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_MTFIRFilterCCF = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_MTFIRFilterCCF_MTFIRFilterCCF_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_MTFIRFilterCCF_MTFIRFilterCCF_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_MTFIRFilterCCF_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_MTFIRFilterCCF_set_taps = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_lfast_MTFIRFilterCCF_taps = R"doc()doc"; 35 | 36 | 37 | -------------------------------------------------------------------------------- /grc/lfast_MTFIRFilterXX.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_MTFIRFilterXX 4 | label: Multithreaded FIR Filter 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [CCF, CCC, FF] 12 | option_labels: [Complex->Complex (Real Taps), Complex->Complex (Complex Taps), 13 | Float->Float (Real Taps)] 14 | option_attributes: 15 | input: [complex, complex, float] 16 | output: [complex, complex, float] 17 | taps: [real_vector, real_vector, real_vector] 18 | hide: part 19 | - id: nthreads 20 | label: Threads 21 | dtype: int 22 | default: '4' 23 | - id: taps 24 | label: Taps 25 | dtype: ${ type.taps } 26 | 27 | inputs: 28 | - domain: stream 29 | dtype: ${ type.input } 30 | 31 | outputs: 32 | - domain: stream 33 | dtype: ${ type.output } 34 | 35 | templates: 36 | imports: import lfast 37 | make: lfast.MTFIRFilter${type}(1, ${taps}, ${nthreads}) 38 | callbacks: 39 | - set_taps(${taps}) 40 | 41 | file_format: 1 42 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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-lfast 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}/lfast 26 | ) 27 | 28 | ######################################################################## 29 | # Handle the unit tests 30 | ######################################################################## 31 | include(GrTest) 32 | 33 | set(GR_TEST_TARGET_DEPS gnuradio-lfast) 34 | -------------------------------------------------------------------------------- /include/lfast/api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * GNU Radio is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3, or (at your option) 9 | * any later version. 10 | * 11 | * GNU Radio is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with GNU Radio; see the file COPYING. If not, write to 18 | * the Free Software Foundation, Inc., 51 Franklin Street, 19 | * Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifndef INCLUDED_LFAST_API_H 23 | #define INCLUDED_LFAST_API_H 24 | 25 | #include 26 | 27 | #ifdef gnuradio_lfast_EXPORTS 28 | # define LFAST_API __GR_ATTR_EXPORT 29 | #else 30 | # define LFAST_API __GR_ATTR_IMPORT 31 | #endif 32 | 33 | #endif /* INCLUDED_LFAST_API_H */ 34 | -------------------------------------------------------------------------------- /include/lfast/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011,2012 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | ######################################################################## 21 | # Install public header files 22 | ######################################################################## 23 | install(FILES 24 | api.h 25 | costas2.h 26 | costas4.h 27 | agc_fast.h 28 | CC2F2ByteVector.h 29 | nlog10volk.h 30 | quad_demod_volk.h 31 | MTFIRFilterCCF.h 32 | MTFIRFilterFF.h 33 | MTFIRFilterCCC.h DESTINATION include/lfast 34 | ) 35 | -------------------------------------------------------------------------------- /grc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Free Software Foundation, Inc. 2 | # 3 | # This file is part of GNU Radio 4 | # 5 | # GNU Radio is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 3, or (at your option) 8 | # any later version. 9 | # 10 | # GNU Radio is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with GNU Radio; see the file COPYING. If not, write to 17 | # the Free Software Foundation, Inc., 51 Franklin Street, 18 | # Boston, MA 02110-1301, USA. 19 | 20 | install(FILES 21 | lfast_freq_shift.block.yml 22 | lfast_costas2.block.yml 23 | lfast_costas4.block.yml 24 | lfast_agc_fast.block.yml 25 | lfast_agc_fast_ff.block.yml 26 | lfast_CC2F2ByteVector.block.yml 27 | lfast_low_pass_filter.block.yml 28 | lfast_high_pass_filter.block.yml 29 | lfast_root_raised_cosine_filter.block.yml 30 | lfast_nlog10volk.block.yml 31 | lfast_MTFIRLowPassFilterXX.block.yml 32 | lfast_MTFIRFilterXX.block.yml 33 | DESTINATION share/gnuradio/grc/blocks 34 | 35 | ) 36 | 37 | # lfast_quad_demod_volk.block.yml -------------------------------------------------------------------------------- /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-lfast 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /python/bindings/docstrings/agc_fast_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_agc_fast = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_agc_fast_agc_fast_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_agc_fast_agc_fast_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_agc_fast_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_agc_fast_rate = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_lfast_agc_fast_reference = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_lfast_agc_fast_gain = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_lfast_agc_fast_max_gain = R"doc()doc"; 41 | 42 | 43 | static const char *__doc_gr_lfast_agc_fast_set_rate = R"doc()doc"; 44 | 45 | 46 | static const char *__doc_gr_lfast_agc_fast_set_reference = R"doc()doc"; 47 | 48 | 49 | static const char *__doc_gr_lfast_agc_fast_set_gain = R"doc()doc"; 50 | 51 | 52 | static const char *__doc_gr_lfast_agc_fast_set_max_gain = R"doc()doc"; 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /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 lfast_sources) 12 | MESSAGE(STATUS "No C++ sources... skipping python bindings") 13 | return() 14 | endif(NOT lfast_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 lfast_python_files 32 | agc_fast_ff_python.cc 33 | agc_fast_python.cc 34 | CC2F2ByteVector_python.cc 35 | costas2_python.cc 36 | costas4_python.cc 37 | MTFIRFilterCCC_python.cc 38 | MTFIRFilterCCF_python.cc 39 | MTFIRFilterFF_python.cc 40 | nlog10volk_python.cc 41 | quad_demod_volk_python.cc python_bindings.cc) 42 | 43 | GR_PYBIND_MAKE_OOT(lfast 44 | ../.. 45 | gr::lfast 46 | "${lfast_python_files}") 47 | 48 | install(TARGETS lfast_python DESTINATION ${GR_PYTHON_DIR}/lfast COMPONENT pythonapi) 49 | -------------------------------------------------------------------------------- /python/bindings/docstrings/agc_fast_ff_pydoc_template.h: -------------------------------------------------------------------------------- 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 | #include "pydoc_macros.h" 10 | #define D(...) DOC(gr,lfast, __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_lfast_agc_fast_ff = R"doc()doc"; 20 | 21 | 22 | static const char *__doc_gr_lfast_agc_fast_ff_agc_fast_ff_0 = R"doc()doc"; 23 | 24 | 25 | static const char *__doc_gr_lfast_agc_fast_ff_agc_fast_ff_1 = R"doc()doc"; 26 | 27 | 28 | static const char *__doc_gr_lfast_agc_fast_ff_make = R"doc()doc"; 29 | 30 | 31 | static const char *__doc_gr_lfast_agc_fast_ff_rate = R"doc()doc"; 32 | 33 | 34 | static const char *__doc_gr_lfast_agc_fast_ff_reference = R"doc()doc"; 35 | 36 | 37 | static const char *__doc_gr_lfast_agc_fast_ff_gain = R"doc()doc"; 38 | 39 | 40 | static const char *__doc_gr_lfast_agc_fast_ff_max_gain = R"doc()doc"; 41 | 42 | 43 | static const char *__doc_gr_lfast_agc_fast_ff_set_rate = R"doc()doc"; 44 | 45 | 46 | static const char *__doc_gr_lfast_agc_fast_ff_set_reference = R"doc()doc"; 47 | 48 | 49 | static const char *__doc_gr_lfast_agc_fast_ff_set_gain = R"doc()doc"; 50 | 51 | 52 | static const char *__doc_gr_lfast_agc_fast_ff_set_max_gain = R"doc()doc"; 53 | 54 | 55 | -------------------------------------------------------------------------------- /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-lfast 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 | -------------------------------------------------------------------------------- /python/bindings/nlog10volk_python.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 | /***********************************************************************************/ 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(nlog10volk.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(d68e42d357ebebbf602d82ecc0098608) */ 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_nlog10volk(py::module& m) 31 | { 32 | 33 | using nlog10volk = ::gr::lfast::nlog10volk; 34 | 35 | 36 | py::class_>(m, "nlog10volk", D(nlog10volk)) 38 | 39 | .def(py::init(&nlog10volk::make), 40 | py::arg("n"), 41 | py::arg("vlen"), 42 | py::arg("k"), 43 | D(nlog10volk,make) 44 | ) 45 | 46 | 47 | 48 | 49 | ; 50 | 51 | 52 | 53 | 54 | } 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /python/bindings/quad_demod_volk_python.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 | /***********************************************************************************/ 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(quad_demod_volk.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(9ac8ced322b4a5ff48a5afc4fdb49fe5) */ 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_quad_demod_volk(py::module& m) 31 | { 32 | 33 | using quad_demod_volk = ::gr::lfast::quad_demod_volk; 34 | 35 | 36 | py::class_>(m, "quad_demod_volk", D(quad_demod_volk)) 38 | 39 | .def(py::init(&quad_demod_volk::make), 40 | py::arg("gain"), 41 | D(quad_demod_volk,make) 42 | ) 43 | 44 | 45 | 46 | 47 | ; 48 | 49 | 50 | 51 | 52 | } 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /python/bindings/CC2F2ByteVector_python.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 | /***********************************************************************************/ 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(CC2F2ByteVector.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(e1b9616c3e4c6b4a11825a9f73c3c9ac) */ 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_CC2F2ByteVector(py::module& m) 31 | { 32 | 33 | using CC2F2ByteVector = ::gr::lfast::CC2F2ByteVector; 34 | 35 | 36 | py::class_>(m, "CC2F2ByteVector", D(CC2F2ByteVector)) 38 | 39 | .def(py::init(&CC2F2ByteVector::make), 40 | py::arg("scale") = 1, 41 | py::arg("vecLength") = 1, 42 | py::arg("numVecItems") = 1, 43 | D(CC2F2ByteVector,make) 44 | ) 45 | 46 | 47 | 48 | 49 | ; 50 | 51 | 52 | 53 | 54 | } 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /python/bindings/costas2_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(costas2.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(67b06f96d3c792aea17cb1f00727ffbc) */ 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_costas2(py::module& m) 31 | { 32 | 33 | using costas2 = ::gr::lfast::costas2; 34 | 35 | 36 | py::class_>(m, "costas2", D(costas2)) 38 | 39 | .def(py::init(&costas2::make), 40 | py::arg("loop_bw"), 41 | py::arg("order"), 42 | py::arg("genPDUs"), 43 | D(costas2,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("error",&costas2::error, 52 | D(costas2,error) 53 | ) 54 | 55 | ; 56 | 57 | 58 | 59 | 60 | } 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /python/bindings/costas4_python.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GNU Radio 5 | * 6 | * SPDX-License-Identifier: GPL-3.0-or-later 7 | * 8 | */ 9 | 10 | /***********************************************************************************/ 11 | /* This file is automatically generated using bindtool and can be manually edited */ 12 | /* The following lines can be configured to regenerate this file during cmake */ 13 | /* If manual edits are made, the following tags should be modified accordingly. */ 14 | /* BINDTOOL_GEN_AUTOMATIC(0) */ 15 | /* BINDTOOL_USE_PYGCCXML(0) */ 16 | /* BINDTOOL_HEADER_FILE(costas4.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(07e40df1c47bcd5e7e7231e1aade786a) */ 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_costas4(py::module& m) 31 | { 32 | 33 | using costas4 = ::gr::lfast::costas4; 34 | 35 | 36 | py::class_>(m, "costas4", D(costas4)) 38 | 39 | .def(py::init(&costas4::make), 40 | py::arg("loop_bw"), 41 | py::arg("order"), 42 | py::arg("genPDUs"), 43 | D(costas4,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("error",&costas4::error, 52 | D(costas4,error) 53 | ) 54 | 55 | ; 56 | 57 | 58 | 59 | 60 | } 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /include/lfast/CC2F2ByteVector.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 | 22 | #ifndef INCLUDED_TESTTIMING_CC2F2BYTEVECTOR_H 23 | #define INCLUDED_TESTTIMING_CC2F2BYTEVECTOR_H 24 | 25 | #include 26 | #include 27 | 28 | namespace gr { 29 | namespace lfast { 30 | 31 | /*! 32 | * \brief <+description of block+> 33 | * \ingroup testtiming 34 | * 35 | */ 36 | class LFAST_API CC2F2ByteVector : virtual public gr::sync_decimator 37 | { 38 | public: 39 | typedef std::shared_ptr sptr; 40 | 41 | /*! 42 | * \brief Return a shared_ptr to a new instance of testtiming::CC2F2ByteVector. 43 | * 44 | * To avoid accidental use of raw pointers, testtiming::CC2F2ByteVector's 45 | * constructor is in a private implementation 46 | * class. testtiming::CC2F2ByteVector::make is the public interface for 47 | * creating new instances. 48 | */ 49 | static sptr make(int scale=1,int vecLength=1,int numVecItems=1); 50 | }; 51 | 52 | } // namespace testtiming 53 | } // namespace gr 54 | 55 | #endif /* INCLUDED_TESTTIMING_CC2F2BYTEVECTOR_H */ 56 | 57 | -------------------------------------------------------------------------------- /include/lfast/costas2.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 | 22 | #ifndef INCLUDED_LFAST_COSTAS2_H 23 | #define INCLUDED_LFAST_COSTAS2_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace gr { 30 | namespace lfast { 31 | 32 | /*! 33 | * \brief <+description of block+> 34 | * \ingroup lfast 35 | * 36 | */ 37 | class LFAST_API costas2 38 | : virtual public gr::sync_block, 39 | virtual public blocks::control_loop 40 | { 41 | public: 42 | typedef std::shared_ptr sptr; 43 | 44 | /*! 45 | * \brief Return a shared_ptr to a new instance of lfast::costas2. 46 | * 47 | * To avoid accidental use of raw pointers, lfast::costas2's 48 | * constructor is in a private implementation 49 | * class. lfast::costas2::make is the public interface for 50 | * creating new instances. 51 | */ 52 | static sptr make(float loop_bw, int order, bool genPDUs); 53 | 54 | virtual float error() const = 0; 55 | }; 56 | 57 | } // namespace lfast 58 | } // namespace gr 59 | 60 | #endif /* INCLUDED_LFAST_COSTAS2_H */ 61 | 62 | -------------------------------------------------------------------------------- /include/lfast/costas4.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 | 22 | #ifndef INCLUDED_LFAST_COSTAS4_H 23 | #define INCLUDED_LFAST_COSTAS4_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace gr { 30 | namespace lfast { 31 | 32 | /*! 33 | * \brief <+description of block+> 34 | * \ingroup lfast 35 | * 36 | */ 37 | class LFAST_API costas4 38 | : virtual public gr::sync_block, 39 | virtual public blocks::control_loop 40 | { 41 | public: 42 | typedef std::shared_ptr sptr; 43 | 44 | /*! 45 | * \brief Return a shared_ptr to a new instance of lfast::costas4. 46 | * 47 | * To avoid accidental use of raw pointers, lfast::costas2's 48 | * constructor is in a private implementation 49 | * class. lfast::costas2::make is the public interface for 50 | * creating new instances. 51 | */ 52 | static sptr make(float loop_bw, int order, bool genPDUs); 53 | 54 | virtual float error() const = 0; 55 | }; 56 | 57 | } // namespace lfast 58 | } // namespace gr 59 | 60 | #endif /* INCLUDED_LFAST_COSTAS4_H */ 61 | 62 | -------------------------------------------------------------------------------- /grc/lfast_root_raised_cosine_filter.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_rrc_filter 4 | label: FFT Root Raised Cosine Filter 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [ccc, ccf, fff] 12 | option_labels: [Complex->Complex (Complex Taps), Complex->Complex (Real Taps), 13 | Float->Float (Real Taps)] 14 | option_attributes: 15 | input: [complex, complex, float] 16 | output: [complex, complex, float] 17 | taps: [complex_vector, float_vector, float_vector] 18 | hide: part 19 | - id: decim 20 | label: Decimation 21 | dtype: int 22 | default: '1' 23 | - id: gain 24 | label: Gain 25 | dtype: real 26 | default: '1' 27 | - id: samp_rate 28 | label: Sample Rate 29 | dtype: real 30 | default: samp_rate 31 | - id: sym_rate 32 | label: Symbol Rate 33 | dtype: real 34 | default: '1.0' 35 | - id: alpha 36 | label: Alpha 37 | dtype: real 38 | default: '0.35' 39 | - id: ntaps 40 | label: Num Taps 41 | dtype: int 42 | default: 11*samp_rate 43 | - id: nthreads 44 | label: Num. Threads 45 | dtype: int 46 | default: '1' 47 | 48 | inputs: 49 | - domain: stream 50 | dtype: ${ type.input } 51 | 52 | outputs: 53 | - domain: stream 54 | dtype: ${ type.output } 55 | 56 | templates: 57 | imports: |- 58 | from gnuradio import filter 59 | from gnuradio.filter import firdes 60 | make: filter.fft_filter_${type}(${decim}, firdes.root_raised_cosine(${gain}, ${samp_rate}, 61 | ${sym_rate}, ${alpha}, ${ntaps}), ${nthreads}) 62 | callbacks: 63 | - set_taps(firdes.root_raised_cosine(${gain}, ${samp_rate}, ${sym_rate}, ${alpha}, 64 | ${ntaps})) 65 | - set_nthreads(${nthreads}) 66 | 67 | documentation: |- 68 | This filter is a convenience wrapper for an FFT-based Root Raised Cosine filter and a firdes taps generating function. 69 | 70 | Sample rate in Hertz. 71 | 72 | file_format: 1 73 | -------------------------------------------------------------------------------- /python/bindings/MTFIRFilterFF_python.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 | /***********************************************************************************/ 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(MTFIRFilterFF.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(16914d02353fea6618bea70cc00b3e3d) */ 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_MTFIRFilterFF(py::module& m) 31 | { 32 | 33 | using MTFIRFilterFF = ::gr::lfast::MTFIRFilterFF; 34 | 35 | 36 | py::class_>(m, "MTFIRFilterFF", D(MTFIRFilterFF)) 38 | 39 | .def(py::init(&MTFIRFilterFF::make), 40 | py::arg("decimation"), 41 | py::arg("taps"), 42 | py::arg("nthreads"), 43 | D(MTFIRFilterFF,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("set_taps",&MTFIRFilterFF::set_taps, 52 | py::arg("taps"), 53 | D(MTFIRFilterFF,set_taps) 54 | ) 55 | 56 | 57 | 58 | .def("taps",&MTFIRFilterFF::taps, 59 | D(MTFIRFilterFF,taps) 60 | ) 61 | 62 | ; 63 | 64 | 65 | 66 | 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /grc/lfast_MTFIRLowPassFilterXX.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_MTFIRLowPassFilterXX 4 | label: Multithreaded Low Pass FIR Filter 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [CCF, FF] 12 | option_labels: [Complex->Complex (Real Taps), Float->Float (Real Taps)] 13 | option_attributes: 14 | input: [complex, float] 15 | output: [complex, float] 16 | taps: [real_vector, real_vector] 17 | hide: part 18 | - id: nthreads 19 | label: Threads 20 | dtype: int 21 | default: '4' 22 | - id: gain 23 | label: Gain 24 | dtype: real 25 | default: '1' 26 | - id: samp_rate 27 | label: Sample Rate 28 | dtype: real 29 | default: samp_rate 30 | - id: cutoff_freq 31 | label: Cutoff Freq 32 | dtype: real 33 | - id: width 34 | label: Transition Width 35 | dtype: real 36 | - id: win 37 | label: Window 38 | dtype: enum 39 | default: window.WIN_HAMMING 40 | options: [window.WIN_HAMMING, window.WIN_HANN, window.WIN_BLACKMAN, window.WIN_RECTANGULAR, 41 | window.WIN_KAISER] 42 | option_labels: [Hamming, Hann, Blackman, Rectangular, Kaiser] 43 | - id: beta 44 | label: Beta 45 | dtype: real 46 | default: '6.76' 47 | 48 | inputs: 49 | - domain: stream 50 | dtype: ${ type.input } 51 | 52 | outputs: 53 | - domain: stream 54 | dtype: ${ type.output } 55 | 56 | templates: 57 | imports: |- 58 | import lfast 59 | from gnuradio.filter import firdes 60 | from gnuradio.fft import window 61 | make: lfast.MTFIRFilter${type}(1, firdes.low_pass(${gain}, ${samp_rate}, ${cutoff_freq}, 62 | ${width}, ${win}, ${beta}), ${nthreads}) 63 | callbacks: 64 | - set_taps(firdes.low_pass(${gain}, ${samp_rate}, ${cutoff_freq}, ${width}, ${win}, 65 | ${beta})) 66 | 67 | documentation: |- 68 | This filter is a convenience wrapper for an fir filter and a firdes taps generating function. 69 | 70 | Sample rate, cutoff frequency, and transition width are in Hertz. 71 | 72 | The beta parameter only applies to the Kaiser window. 73 | 74 | file_format: 1 75 | -------------------------------------------------------------------------------- /python/bindings/MTFIRFilterCCC_python.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 | /***********************************************************************************/ 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(MTFIRFilterCCC.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(f8f9d735ffa6fb4e174073ee0642fc6b) */ 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_MTFIRFilterCCC(py::module& m) 31 | { 32 | 33 | using MTFIRFilterCCC = ::gr::lfast::MTFIRFilterCCC; 34 | 35 | 36 | py::class_>(m, "MTFIRFilterCCC", D(MTFIRFilterCCC)) 38 | 39 | .def(py::init(&MTFIRFilterCCC::make), 40 | py::arg("decimation"), 41 | py::arg("taps"), 42 | py::arg("nthreads"), 43 | D(MTFIRFilterCCC,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("set_taps",&MTFIRFilterCCC::set_taps, 52 | py::arg("taps"), 53 | D(MTFIRFilterCCC,set_taps) 54 | ) 55 | 56 | 57 | 58 | .def("taps",&MTFIRFilterCCC::taps, 59 | D(MTFIRFilterCCC,taps) 60 | ) 61 | 62 | ; 63 | 64 | 65 | 66 | 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /python/bindings/MTFIRFilterCCF_python.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 | /***********************************************************************************/ 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(MTFIRFilterCCF.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(983a0f4b4b48b4bb69ea58b2df23d301) */ 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_MTFIRFilterCCF(py::module& m) 31 | { 32 | 33 | using MTFIRFilterCCF = ::gr::lfast::MTFIRFilterCCF; 34 | 35 | 36 | py::class_>(m, "MTFIRFilterCCF", D(MTFIRFilterCCF)) 38 | 39 | .def(py::init(&MTFIRFilterCCF::make), 40 | py::arg("decimation"), 41 | py::arg("taps"), 42 | py::arg("nthreads"), 43 | D(MTFIRFilterCCF,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("set_taps",&MTFIRFilterCCF::set_taps, 52 | py::arg("taps"), 53 | D(MTFIRFilterCCF,set_taps) 54 | ) 55 | 56 | 57 | 58 | .def("taps",&MTFIRFilterCCF::taps, 59 | D(MTFIRFilterCCF,taps) 60 | ) 61 | 62 | ; 63 | 64 | 65 | 66 | 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /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-lfast 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/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 | -------------------------------------------------------------------------------- /include/lfast/agc_fast_ff.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 | 22 | #ifndef INCLUDED_LFAST_AGC_FAST_FF_H 23 | #define INCLUDED_LFAST_AGC_FAST_FF_H 24 | 25 | #include 26 | #include 27 | 28 | namespace gr { 29 | namespace lfast { 30 | 31 | /*! 32 | * \brief <+description of block+> 33 | * \ingroup lfast 34 | * 35 | */ 36 | class LFAST_API agc_fast_ff : virtual public gr::sync_block 37 | { 38 | public: 39 | typedef std::shared_ptr sptr; 40 | 41 | /*! 42 | * \brief Return a shared_ptr to a new instance of lfast::agc_fast. 43 | * 44 | * To avoid accidental use of raw pointers, lfast::agc_fast's 45 | * constructor is in a private implementation 46 | * class. lfast::agc_fast::make is the public interface for 47 | * creating new instances. 48 | */ 49 | static sptr make(float rate = 1e-4, float reference = 1.0, float gain = 1.0); 50 | virtual float rate() const = 0; 51 | virtual float reference() const = 0; 52 | virtual float gain() const = 0; 53 | virtual float max_gain() const = 0; 54 | 55 | virtual void set_rate(float rate) = 0; 56 | virtual void set_reference(float reference) = 0; 57 | virtual void set_gain(float gain) = 0; 58 | virtual void set_max_gain(float max_gain) = 0; 59 | }; 60 | 61 | } // namespace lfast 62 | } // namespace gr 63 | 64 | #endif /* INCLUDED_LFAST_AGC_FAST_FF_H */ 65 | 66 | -------------------------------------------------------------------------------- /include/lfast/agc_fast.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 | 22 | #ifndef INCLUDED_LFAST_AGC_FAST_H 23 | #define INCLUDED_LFAST_AGC_FAST_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace gr { 30 | namespace lfast { 31 | 32 | /*! 33 | * \brief <+description of block+> 34 | * \ingroup lfast 35 | * 36 | */ 37 | class LFAST_API agc_fast : virtual public gr::sync_block 38 | { 39 | public: 40 | typedef std::shared_ptr sptr; 41 | 42 | /*! 43 | * \brief Return a shared_ptr to a new instance of lfast::agc_fast. 44 | * 45 | * To avoid accidental use of raw pointers, lfast::agc_fast's 46 | * constructor is in a private implementation 47 | * class. lfast::agc_fast::make is the public interface for 48 | * creating new instances. 49 | */ 50 | static sptr make(float rate = 1e-4, float reference = 1.0, float gain = 1.0); 51 | virtual float rate() const = 0; 52 | virtual float reference() const = 0; 53 | virtual float gain() const = 0; 54 | virtual float max_gain() const = 0; 55 | 56 | virtual void set_rate(float rate) = 0; 57 | virtual void set_reference(float reference) = 0; 58 | virtual void set_gain(float gain) = 0; 59 | virtual void set_max_gain(float max_gain) = 0; 60 | }; 61 | 62 | } // namespace lfast 63 | } // namespace gr 64 | 65 | #endif /* INCLUDED_LFAST_AGC_FAST_H */ 66 | 67 | -------------------------------------------------------------------------------- /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/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_agc_fast_ff(py::module& m); 25 | void bind_agc_fast(py::module& m); 26 | void bind_CC2F2ByteVector(py::module& m); 27 | void bind_costas2(py::module& m); 28 | void bind_costas4(py::module& m); 29 | void bind_MTFIRFilterCCC(py::module& m); 30 | void bind_MTFIRFilterCCF(py::module& m); 31 | void bind_MTFIRFilterFF(py::module& m); 32 | void bind_nlog10volk(py::module& m); 33 | void bind_quad_demod_volk(py::module& m); 34 | // ) END BINDING_FUNCTION_PROTOTYPES 35 | 36 | 37 | // We need this hack because import_array() returns NULL 38 | // for newer Python versions. 39 | // This function is also necessary because it ensures access to the C API 40 | // and removes a warning. 41 | void* init_numpy() 42 | { 43 | import_array(); 44 | return NULL; 45 | } 46 | 47 | PYBIND11_MODULE(lfast_python, m) 48 | { 49 | // Initialize the numpy C API 50 | // (otherwise we will see segmentation faults) 51 | init_numpy(); 52 | 53 | // Allow access to base block methods 54 | py::module::import("gnuradio.gr"); 55 | 56 | /**************************************/ 57 | /* The following comment block is used for 58 | /* gr_modtool to insert binding function calls 59 | /* Please do not delete 60 | /**************************************/ 61 | // BINDING_FUNCTION_CALLS( 62 | bind_agc_fast_ff(m); 63 | bind_agc_fast(m); 64 | bind_CC2F2ByteVector(m); 65 | bind_costas2(m); 66 | bind_costas4(m); 67 | bind_MTFIRFilterCCC(m); 68 | bind_MTFIRFilterCCF(m); 69 | bind_MTFIRFilterFF(m); 70 | bind_nlog10volk(m); 71 | bind_quad_demod_volk(m); 72 | // ) END BINDING_FUNCTION_CALLS 73 | } -------------------------------------------------------------------------------- /grc/lfast_high_pass_filter.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_high_pass_filter 4 | label: FFT High Pass Filter 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [ccc, ccf, fff] 12 | option_labels: [Complex->Complex (Complex Taps), Complex->Complex (Real Taps), 13 | Float->Float (Real Taps)] 14 | option_attributes: 15 | input: [complex, complex, float] 16 | output: [complex, complex, float] 17 | taps: [complex_vector, float_vector, float_vector] 18 | hide: part 19 | - id: decim 20 | label: Decimation 21 | dtype: int 22 | default: '1' 23 | - id: gain 24 | label: Gain 25 | dtype: real 26 | default: '1' 27 | - id: samp_rate 28 | label: Sample Rate 29 | dtype: real 30 | default: samp_rate 31 | - id: cutoff_freq 32 | label: Cutoff Freq 33 | dtype: real 34 | - id: width 35 | label: Transition Width 36 | dtype: real 37 | - id: win 38 | label: Window 39 | dtype: int 40 | default: window.WIN_HAMMING 41 | options: [window.WIN_HAMMING, window.WIN_HANN, window.WIN_BLACKMAN, window.WIN_RECTANGULAR, 42 | window.WIN_KAISER] 43 | option_labels: [Hamming, Hann, Blackman, Rectangular, Kaiser] 44 | - id: beta 45 | label: Beta 46 | dtype: real 47 | default: '6.76' 48 | - id: nthreads 49 | label: Num. Threads 50 | dtype: int 51 | default: '1' 52 | 53 | inputs: 54 | - domain: stream 55 | dtype: ${ type.input } 56 | 57 | outputs: 58 | - domain: stream 59 | dtype: ${ type.output } 60 | 61 | templates: 62 | imports: |- 63 | from gnuradio import filter 64 | from gnuradio.filter import firdes 65 | make: filter.fft_filter_${type}(${decim}, firdes.high_pass(${gain}, ${samp_rate}, 66 | ${cutoff_freq}, ${width}, ${win}, ${beta}), ${nthreads}) 67 | callbacks: 68 | - set_taps(firdes.high_pass(${gain}, ${samp_rate}, ${cutoff_freq}, ${width}, ${win}, 69 | ${beta})) 70 | - set_nthreads(${nthreads}) 71 | 72 | documentation: |- 73 | This filter is a convenience wrapper for an FFT-based low-pass filter. 74 | 75 | Sample rate, cutoff frequency, and transition width are in Hertz. 76 | 77 | The beta paramater only applies to the Kaiser window. 78 | 79 | file_format: 1 80 | -------------------------------------------------------------------------------- /lib/costas2_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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_LFAST_COSTAS2_IMPL_H 22 | #define INCLUDED_LFAST_COSTAS2_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace lfast { 28 | 29 | class costas2_impl : public costas2 30 | { 31 | private: 32 | int d_order; 33 | float d_error; 34 | float d_noise; 35 | 36 | bool d_genSignalPDUs; 37 | 38 | float 39 | phase_detector_2(gr_complex sample) const 40 | { 41 | return (sample.real()*sample.imag()); 42 | } 43 | 44 | float (costas2_impl::*d_phase_detector)(gr_complex sample) const; 45 | 46 | public: 47 | costas2_impl(float loop_bw, int order, bool genPDUs); 48 | ~costas2_impl(); 49 | 50 | float error() const; 51 | 52 | // void printSineError(); 53 | 54 | void handle_set_noise(pmt::pmt_t msg); 55 | 56 | void handleMsgIn(pmt::pmt_t msg); 57 | 58 | // Where all the action really happens 59 | int work(int noutput_items, 60 | gr_vector_const_void_star &input_items, 61 | gr_vector_void_star &output_items); 62 | int work_original(int noutput_items, 63 | gr_vector_const_void_star &input_items, 64 | gr_vector_void_star &output_items); 65 | int work_test(int noutput_items, 66 | gr_vector_const_void_star &input_items, 67 | gr_vector_void_star &output_items); 68 | }; 69 | 70 | } // namespace lfast 71 | } // namespace gr 72 | 73 | #endif /* INCLUDED_LFAST_COSTAS2_IMPL_H */ 74 | 75 | -------------------------------------------------------------------------------- /grc/lfast_low_pass_filter.block.yml: -------------------------------------------------------------------------------- 1 | # auto-generated by grc.converter 2 | 3 | id: lfast_low_pass_filter 4 | label: FFT Low Pass Filter 5 | category: '[LFAST Accelerated Blocks]' 6 | 7 | parameters: 8 | - id: type 9 | label: Type 10 | dtype: enum 11 | options: [ccc, ccf, fff] 12 | option_labels: [Complex->Complex (Complex Taps), Complex->Complex (Real Taps), 13 | Float->Float (Real Taps)] 14 | option_attributes: 15 | input: [complex, complex, float] 16 | output: [complex, complex, float] 17 | taps: [complex_vector, float_vector, float_vector] 18 | hide: part 19 | - id: decim 20 | label: Decimation 21 | dtype: int 22 | default: '1' 23 | - id: gain 24 | label: Gain 25 | dtype: real 26 | default: '1' 27 | - id: samp_rate 28 | label: Sample Rate 29 | dtype: real 30 | default: samp_rate 31 | - id: cutoff_freq 32 | label: Cutoff Freq 33 | dtype: real 34 | - id: width 35 | label: Transition Width 36 | dtype: real 37 | - id: win 38 | label: Window 39 | dtype: int 40 | default: window.WIN_HAMMING 41 | options: [window.WIN_HAMMING, window.WIN_HANN, window.WIN_BLACKMAN, window.WIN_RECTANGULAR, 42 | window.WIN_KAISER] 43 | option_labels: [Hamming, Hann, Blackman, Rectangular, Kaiser] 44 | - id: beta 45 | label: Beta 46 | dtype: real 47 | default: '6.76' 48 | - id: nthreads 49 | label: Num. Threads 50 | dtype: int 51 | default: '1' 52 | 53 | inputs: 54 | - domain: stream 55 | dtype: ${ type.input } 56 | 57 | outputs: 58 | - domain: stream 59 | dtype: ${ type.output } 60 | 61 | templates: 62 | imports: |- 63 | from gnuradio import filter 64 | from gnuradio.filter import firdes 65 | from gnuradio.fft import window 66 | make: filter.fft_filter_${type}(${decim}, firdes.low_pass(${gain}, ${samp_rate}, 67 | ${cutoff_freq}, ${width}, ${win}, ${beta}), ${nthreads}) 68 | callbacks: 69 | - set_taps(firdes.low_pass(${gain}, ${samp_rate}, ${cutoff_freq}, ${width}, ${win}, 70 | ${beta})) 71 | - set_nthreads(${nthreads}) 72 | 73 | documentation: |- 74 | This filter is a convenience wrapper for an FFT-based low-pass filter. 75 | 76 | Sample rate, cutoff frequency, and transition width are in Hertz. 77 | 78 | The beta paramater only applies to the Kaiser window. 79 | 80 | file_format: 1 81 | -------------------------------------------------------------------------------- /lib/agc_fast_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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_LFAST_AGC_FAST_IMPL_H 22 | #define INCLUDED_LFAST_AGC_FAST_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace lfast { 28 | 29 | class agc_fast_impl : public agc_fast,kernel::agc_cc 30 | { 31 | private: 32 | // Nothing to declare in this block. 33 | 34 | public: 35 | agc_fast_impl(float rate = 1e-4, float reference = 1.0, 36 | float gain = 1.0); 37 | ~agc_fast_impl(); 38 | 39 | float rate() const { return kernel::agc_cc::rate(); } 40 | float reference() const { return kernel::agc_cc::reference(); } 41 | float gain() const { return kernel::agc_cc::gain(); } 42 | float max_gain() const { return kernel::agc_cc::max_gain(); } 43 | 44 | void set_rate(float rate) { kernel::agc_cc::set_rate(rate); } 45 | void set_reference(float reference) { kernel::agc_cc::set_reference(reference); } 46 | void set_gain(float gain) { kernel::agc_cc::set_gain(gain); } 47 | virtual void set_max_gain(float max_gain) { kernel::agc_cc::set_max_gain(max_gain); } 48 | 49 | // Where all the action really happens 50 | int work(int noutput_items, 51 | gr_vector_const_void_star &input_items, 52 | gr_vector_void_star &output_items); 53 | 54 | int work_original(int noutput_items, 55 | gr_vector_const_void_star &input_items, 56 | gr_vector_void_star &output_items); 57 | int work_test(int noutput_items, 58 | gr_vector_const_void_star &input_items, 59 | gr_vector_void_star &output_items); 60 | }; 61 | 62 | } // namespace lfast 63 | } // namespace gr 64 | 65 | #endif /* INCLUDED_LFAST_AGC_FAST_IMPL_H */ 66 | 67 | -------------------------------------------------------------------------------- /lib/costas4_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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_LFAST_costas4_IMPL_H 22 | #define INCLUDED_LFAST_costas4_IMPL_H 23 | 24 | #include 25 | 26 | namespace gr { 27 | namespace lfast { 28 | 29 | class costas4_impl : public costas4 30 | { 31 | private: 32 | int d_order; 33 | float d_error; 34 | float d_noise; 35 | bool d_genSignalPDUs; 36 | 37 | float 38 | phase_detector_2(gr_complex sample) const 39 | { 40 | return (sample.real()*sample.imag()); 41 | } 42 | 43 | float 44 | phase_detector_4(gr_complex sample) const 45 | { 46 | return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - 47 | (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); 48 | } 49 | 50 | 51 | float (costas4_impl::*d_phase_detector)(gr_complex sample) const; 52 | 53 | public: 54 | costas4_impl(float loop_bw, int order, bool genPDUs); 55 | ~costas4_impl(); 56 | 57 | float error() const; 58 | 59 | void handleMsgIn(pmt::pmt_t msg); 60 | 61 | // void printSineError(); 62 | 63 | void handle_set_noise(pmt::pmt_t msg); 64 | 65 | // Where all the action really happens 66 | int work(int noutput_items, 67 | gr_vector_const_void_star &input_items, 68 | gr_vector_void_star &output_items); 69 | int work_original(int noutput_items, 70 | gr_vector_const_void_star &input_items, 71 | gr_vector_void_star &output_items); 72 | int work_test(int noutput_items, 73 | gr_vector_const_void_star &input_items, 74 | gr_vector_void_star &output_items); 75 | }; 76 | 77 | } // namespace lfast 78 | } // namespace gr 79 | 80 | #endif /* INCLUDED_LFAST_costas4_IMPL_H */ 81 | 82 | -------------------------------------------------------------------------------- /lib/CC2F2ByteVector_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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_TESTTIMING_CC2F2BYTEVECTOR_IMPL_H 22 | #define INCLUDED_TESTTIMING_CC2F2BYTEVECTOR_IMPL_H 23 | 24 | #include 25 | #include 26 | 27 | #define LF_MAX_THREADS 8 28 | 29 | namespace gr { 30 | namespace lfast { 31 | 32 | class CC2F2ByteVector_impl : public CC2F2ByteVector 33 | { 34 | protected: 35 | int d_scale; 36 | int d_vlen; 37 | 38 | boost::thread *threads[LF_MAX_THREADS]; 39 | bool dataReady[LF_MAX_THREADS]; 40 | long threadBlockSize[LF_MAX_THREADS]; 41 | long startIndex[LF_MAX_THREADS]; 42 | const gr_complex *inBuffer; 43 | char *outBuffer; 44 | 45 | unsigned concurentThreadsSupported; 46 | unsigned concurrentMinus1; 47 | 48 | bool stopThreads; 49 | 50 | boost::mutex d_mutex; 51 | 52 | float min_val = -128; 53 | float max_val = 127; 54 | 55 | float *floatBuff = NULL; 56 | int curBufferSize=0; 57 | 58 | void processItems(int threadIndex); 59 | 60 | public: 61 | CC2F2ByteVector_impl(int scale,int vecLength,int numVecItems); 62 | ~CC2F2ByteVector_impl(); 63 | virtual bool stop(); 64 | void setBufferLength(int numItems); 65 | 66 | // Where all the action really happens 67 | int work_original(int noutput_items, 68 | gr_vector_const_void_star &input_items, 69 | gr_vector_void_star &output_items); 70 | int work_test(int noutput_items, 71 | gr_vector_const_void_star &input_items, 72 | gr_vector_void_star &output_items); 73 | int work(int noutput_items, 74 | gr_vector_const_void_star &input_items, 75 | gr_vector_void_star &output_items); 76 | }; 77 | 78 | } // namespace testtiming 79 | } // namespace gr 80 | 81 | #endif /* INCLUDED_TESTTIMING_CC2F2BYTEVECTOR_IMPL_H */ 82 | 83 | -------------------------------------------------------------------------------- /lib/agc_fast_ff_impl.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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_LFAST_AGC_FAST_FF_IMPL_H 22 | #define INCLUDED_LFAST_AGC_FAST_FF_IMPL_H 23 | 24 | #include 25 | #include 26 | 27 | namespace gr { 28 | namespace lfast { 29 | 30 | class agc_fast_ff_impl : public agc_fast_ff,gr::analog::kernel::agc_ff 31 | { 32 | private: 33 | // Nothing to declare in this block. 34 | 35 | public: 36 | agc_fast_ff_impl(float rate = 1e-4, float reference = 1.0, 37 | float gain = 1.0); 38 | ~agc_fast_ff_impl(); 39 | 40 | float rate() const { return gr::analog::kernel::agc_ff::rate(); } 41 | float reference() const { return gr::analog::kernel::agc_ff::reference(); } 42 | float gain() const { return gr::analog::kernel::agc_ff::gain(); } 43 | float max_gain() const { return gr::analog::kernel::agc_ff::max_gain(); } 44 | 45 | void set_rate(float rate) { gr::analog::kernel::agc_ff::set_rate(rate); } 46 | void set_reference(float reference) { gr::analog::kernel::agc_ff::set_reference(reference); } 47 | void set_gain(float gain) { gr::analog::kernel::agc_ff::set_gain(gain); } 48 | virtual void set_max_gain(float max_gain) { gr::analog::kernel::agc_ff::set_max_gain(max_gain); } 49 | 50 | // Where all the action really happens 51 | int work(int noutput_items, 52 | gr_vector_const_void_star &input_items, 53 | gr_vector_void_star &output_items); 54 | 55 | int work_original(int noutput_items, 56 | gr_vector_const_void_star &input_items, 57 | gr_vector_void_star &output_items); 58 | int work_test(int noutput_items, 59 | gr_vector_const_void_star &input_items, 60 | gr_vector_void_star &output_items); 61 | }; 62 | 63 | } // namespace lfast 64 | } // namespace gr 65 | 66 | #endif /* INCLUDED_LFAST_AGC_FAST_IMPL_H */ 67 | 68 | -------------------------------------------------------------------------------- /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/agc_fast_ff_python.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 | /***********************************************************************************/ 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(agc_fast_ff.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(f38e1f27ce92a3cac4580e2bc702df2f) */ 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_agc_fast_ff(py::module& m) 31 | { 32 | 33 | using agc_fast_ff = ::gr::lfast::agc_fast_ff; 34 | 35 | 36 | py::class_>(m, "agc_fast_ff", D(agc_fast_ff)) 38 | 39 | .def(py::init(&agc_fast_ff::make), 40 | py::arg("rate") = 1.0E-4, 41 | py::arg("reference") = 1., 42 | py::arg("gain") = 1., 43 | D(agc_fast_ff,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("rate",&agc_fast_ff::rate, 52 | D(agc_fast_ff,rate) 53 | ) 54 | 55 | 56 | 57 | .def("reference",&agc_fast_ff::reference, 58 | D(agc_fast_ff,reference) 59 | ) 60 | 61 | 62 | 63 | .def("gain",&agc_fast_ff::gain, 64 | D(agc_fast_ff,gain) 65 | ) 66 | 67 | 68 | 69 | .def("max_gain",&agc_fast_ff::max_gain, 70 | D(agc_fast_ff,max_gain) 71 | ) 72 | 73 | 74 | 75 | .def("set_rate",&agc_fast_ff::set_rate, 76 | py::arg("rate"), 77 | D(agc_fast_ff,set_rate) 78 | ) 79 | 80 | 81 | 82 | .def("set_reference",&agc_fast_ff::set_reference, 83 | py::arg("reference"), 84 | D(agc_fast_ff,set_reference) 85 | ) 86 | 87 | 88 | 89 | .def("set_gain",&agc_fast_ff::set_gain, 90 | py::arg("gain"), 91 | D(agc_fast_ff,set_gain) 92 | ) 93 | 94 | 95 | 96 | .def("set_max_gain",&agc_fast_ff::set_max_gain, 97 | py::arg("max_gain"), 98 | D(agc_fast_ff,set_max_gain) 99 | ) 100 | 101 | ; 102 | 103 | 104 | 105 | 106 | } 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /python/bindings/agc_fast_python.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 | /***********************************************************************************/ 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(agc_fast.h) */ 17 | /* BINDTOOL_HEADER_FILE_HASH(f55acbf11fe5c50f0d411d9b32439965) */ 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_agc_fast(py::module& m) 31 | { 32 | 33 | using agc_fast = ::gr::lfast::agc_fast; 34 | 35 | 36 | py::class_>(m, "agc_fast", D(agc_fast)) 38 | 39 | .def(py::init(&agc_fast::make), 40 | py::arg("rate") = 1.0E-4, 41 | py::arg("reference") = 1., 42 | py::arg("gain") = 1., 43 | D(agc_fast,make) 44 | ) 45 | 46 | 47 | 48 | 49 | 50 | 51 | .def("rate",&agc_fast::rate, 52 | D(agc_fast,rate) 53 | ) 54 | 55 | 56 | 57 | .def("reference",&agc_fast::reference, 58 | D(agc_fast,reference) 59 | ) 60 | 61 | 62 | 63 | .def("gain",&agc_fast::gain, 64 | D(agc_fast,gain) 65 | ) 66 | 67 | 68 | 69 | .def("max_gain",&agc_fast::max_gain, 70 | D(agc_fast,max_gain) 71 | ) 72 | 73 | 74 | 75 | .def("set_rate",&agc_fast::set_rate, 76 | py::arg("rate"), 77 | D(agc_fast,set_rate) 78 | ) 79 | 80 | 81 | 82 | .def("set_reference",&agc_fast::set_reference, 83 | py::arg("reference"), 84 | D(agc_fast,set_reference) 85 | ) 86 | 87 | 88 | 89 | .def("set_gain",&agc_fast::set_gain, 90 | py::arg("gain"), 91 | D(agc_fast,set_gain) 92 | ) 93 | 94 | 95 | 96 | .def("set_max_gain",&agc_fast::set_max_gain, 97 | py::arg("max_gain"), 98 | D(agc_fast,set_max_gain) 99 | ) 100 | 101 | ; 102 | 103 | 104 | 105 | py::module m_kernel = m.def_submodule("kernel"); 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | } 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /lib/agc_fast_ff_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 22 | #include "agc_fast_ff_impl.h" 23 | #include 24 | 25 | // assisted detection of Fused Multiply Add (FMA) functionality 26 | #if !defined(__FMA__) && defined(__AVX2__) 27 | #define __FMA__ 1 28 | #endif 29 | 30 | #if defined(FP_FAST_FMA) 31 | #define __FMA__ 1 32 | #endif 33 | 34 | #if defined(__FMA__) 35 | #pragma message "FMA support detected. Compiling for Fused Multiply/Add support." 36 | #else 37 | #pragma message "No FMA support detected. Compiling for normal math." 38 | #endif 39 | 40 | namespace gr { 41 | namespace lfast { 42 | 43 | agc_fast_ff::sptr agc_fast_ff::make(float rate, float reference, float gain) 44 | { 45 | return gnuradio::make_block_sptr(rate, reference, gain); 46 | } 47 | 48 | /* 49 | * The private constructor 50 | */ 51 | agc_fast_ff_impl::agc_fast_ff_impl(float rate, float reference, float gain) 52 | : gr::sync_block("agc_fast_ff", 53 | io_signature::make(1, 1, sizeof(float)), 54 | io_signature::make(1, 1, sizeof(float))), 55 | gr::analog::kernel::agc_ff(rate, reference, gain, 65536) 56 | { 57 | const int alignment_multiple = 58 | volk_get_alignment() / sizeof(float); 59 | set_alignment(std::max(1, alignment_multiple)); 60 | } 61 | 62 | /* 63 | * Our virtual destructor. 64 | */ 65 | agc_fast_ff_impl::~agc_fast_ff_impl() 66 | { 67 | } 68 | 69 | int 70 | agc_fast_ff_impl::work(int noutput_items, 71 | gr_vector_const_void_star &input_items, 72 | gr_vector_void_star &output_items) 73 | { 74 | const float *in = (const float *)input_items[0]; 75 | float *out = (float *)output_items[0]; 76 | 77 | for (int i=0;i 0.0 && _gain > _max_gain) 88 | _gain = _max_gain; 89 | 90 | } 91 | return noutput_items; 92 | } 93 | 94 | int 95 | agc_fast_ff_impl::work_original(int noutput_items, 96 | gr_vector_const_void_star &input_items, 97 | gr_vector_void_star &output_items) 98 | { 99 | const float *in = (const float *)input_items[0]; 100 | float *out = (float *)output_items[0]; 101 | scaleN(out, in, noutput_items); 102 | return noutput_items; 103 | } 104 | int 105 | agc_fast_ff_impl::work_test(int noutput_items, 106 | gr_vector_const_void_star &input_items, 107 | gr_vector_void_star &output_items) 108 | { 109 | const float *in = (const float *)input_items[0]; 110 | float *out = (float *)output_items[0]; 111 | 112 | for (int i=0;i 0.0 && _gain > _max_gain) 123 | _gain = _max_gain; 124 | 125 | } 126 | return noutput_items; 127 | } 128 | } /* namespace lfast */ 129 | } /* namespace gr */ 130 | 131 | -------------------------------------------------------------------------------- /include/lfast/agc.h: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2006,2012 Free Software Foundation, Inc. 4 | * 5 | * This file is part of GNU Radio 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_ANALOG_AGC_H 24 | #define INCLUDED_ANALOG_AGC_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace gr { 31 | namespace lfast { 32 | namespace kernel { 33 | 34 | /*! 35 | * \brief high performance Automatic Gain Control class for complex signals. 36 | * \ingroup level_controllers_blk 37 | * 38 | * \details 39 | * For Power the absolute value of the complex number is used. 40 | */ 41 | class LFAST_API agc_cc 42 | { 43 | public: 44 | /*! 45 | * Construct a complex value AGC loop implementation object. 46 | * 47 | * \param rate the update rate of the loop. 48 | * \param reference reference value to adjust signal power to. 49 | * \param gain initial gain value. 50 | * \param max_gain maximum gain value (0 for unlimited). 51 | */ 52 | agc_cc(float rate = 1e-4, float reference = 1.0, 53 | float gain = 1.0, float max_gain = 0.0) 54 | : _rate(rate), _reference(reference), 55 | _gain(gain), _max_gain(max_gain) {}; 56 | 57 | virtual ~agc_cc() {}; 58 | 59 | float rate() const { return _rate; } 60 | float reference() const { return _reference; } 61 | float gain() const { return _gain; } 62 | float max_gain() const { return _max_gain; } 63 | 64 | void set_rate(float rate) { _rate = rate; } 65 | void set_reference(float reference) { _reference = reference; } 66 | void set_gain(float gain) { _gain = gain; } 67 | void set_max_gain(float max_gain) { _max_gain = max_gain; } 68 | 69 | gr_complex scale(gr_complex input) 70 | { 71 | gr_complex output = input * _gain; 72 | 73 | _gain += _rate * (_reference - sqrt(output.real()*output.real() + 74 | output.imag()*output.imag())); 75 | if(_max_gain > 0.0 && _gain > _max_gain) { 76 | _gain = _max_gain; 77 | } 78 | return output; 79 | } 80 | 81 | void scaleN(gr_complex output[], const gr_complex input[], unsigned n) 82 | { 83 | for(unsigned i = 0; i < n; i++) { 84 | output[i] = scale (input[i]); 85 | } 86 | } 87 | 88 | protected: 89 | float _rate; // adjustment rate 90 | float _reference; // reference value 91 | float _gain; // current gain 92 | float _max_gain; // max allowable gain 93 | }; 94 | 95 | /*! 96 | * \brief high performance Automatic Gain Control class for float signals. 97 | * 98 | * Power is approximated by absolute value 99 | */ 100 | class LFAST_API agc_ff 101 | { 102 | public: 103 | /*! 104 | * Construct a floating point value AGC loop implementation object. 105 | * 106 | * \param rate the update rate of the loop. 107 | * \param reference reference value to adjust signal power to. 108 | * \param gain initial gain value. 109 | * \param max_gain maximum gain value (0 for unlimited). 110 | */ 111 | agc_ff(float rate = 1e-4, float reference = 1.0, 112 | float gain = 1.0, float max_gain = 0.0) 113 | : _rate(rate), _reference(reference), _gain(gain), 114 | _max_gain(max_gain) {}; 115 | 116 | ~agc_ff() {}; 117 | 118 | float rate () const { return _rate; } 119 | float reference () const { return _reference; } 120 | float gain () const { return _gain; } 121 | float max_gain () const { return _max_gain; } 122 | 123 | void set_rate (float rate) { _rate = rate; } 124 | void set_reference (float reference) { _reference = reference; } 125 | void set_gain (float gain) { _gain = gain; } 126 | void set_max_gain (float max_gain) { _max_gain = max_gain; } 127 | 128 | float scale (float input) 129 | { 130 | float output = input * _gain; 131 | _gain += (_reference - fabsf (output)) * _rate; 132 | if(_max_gain > 0.0 && _gain > _max_gain) 133 | _gain = _max_gain; 134 | return output; 135 | } 136 | 137 | void scaleN(float output[], const float input[], unsigned n) 138 | { 139 | for(unsigned i = 0; i < n; i++) 140 | output[i] = scale (input[i]); 141 | } 142 | 143 | protected: 144 | float _rate; // adjustment rate 145 | float _reference; // reference value 146 | float _gain; // current gain 147 | float _max_gain; // maximum gain 148 | }; 149 | 150 | } /* namespace kernel */ 151 | } /* namespace analog */ 152 | } /* namespace gr */ 153 | 154 | #endif /* INCLUDED_ANALOG_AGC_H */ 155 | -------------------------------------------------------------------------------- /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-lfast 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 | # Setup FMA Capabilities Flag 22 | IF(UNIX) 23 | MESSAGE(STATUS "Checking for FMA support...") 24 | IF(APPLE) 25 | EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE CPUINFO) 26 | ELSE(APPLE) 27 | if(EXISTS "/proc/cpuinfo") 28 | EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO) 29 | ELSE() 30 | # If for any reason /proc/cpuinfo does not exist, default to no FMA. 31 | set(CPUINFO "") 32 | ENDIF() 33 | ENDIF(APPLE) 34 | 35 | STRING(REGEX REPLACE "^.*(fma).*$" "fma" FMA_THERE ${CPUINFO}) 36 | STRING(COMPARE EQUAL "fma" "${FMA_THERE}" FMA_TRUE) 37 | IF (FMA_TRUE) 38 | MESSAGE(STATUS "Found FMA support. Setting fma compile flag.") 39 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfma") 40 | ELSE (FMA_TRUE) 41 | MESSAGE(STATUS "FMA support not found. Not setting fma flag.") 42 | ENDIF (FMA_TRUE) 43 | ENDIF() 44 | 45 | IF(CMAKE_BUILD_TYPE MATCHES DEBUG) 46 | MESSAGE(STATUS "building for debug...") 47 | ELSE(CMAKE_BUILD_TYPE MATCHES RELEASE) 48 | MESSAGE(STATUS "Release mode: increasing compiler optimizations...") 49 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3") 50 | ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG) 51 | 52 | ######################################################################## 53 | # Setup library 54 | ######################################################################## 55 | include(GrPlatform) #define LIB_SUFFIX 56 | 57 | list(APPEND lfast_sources 58 | costas2_impl.cc 59 | costas4_impl.cc 60 | agc_fast_impl.cc 61 | agc_fast_ff_impl.cc 62 | CC2F2ByteVector_impl.cc 63 | nlog10volk_impl.cc 64 | quad_demod_volk_impl.cc 65 | MTFIRFilterCCF_impl.cc 66 | MTFIRFilterFF_impl.cc 67 | fir_filter_lfast.cc 68 | MTFIRFilterCCC_impl.cc 69 | ) 70 | 71 | set(lfast_sources "${lfast_sources}" PARENT_SCOPE) 72 | if(NOT lfast_sources) 73 | MESSAGE(STATUS "No C++ sources... skipping lib/") 74 | return() 75 | endif(NOT lfast_sources) 76 | 77 | add_library(gnuradio-lfast SHARED ${lfast_sources}) 78 | target_link_libraries(gnuradio-lfast gnuradio::gnuradio-runtime ${Boost_LIBRARIES} boost_thread gnuradio-blocks gnuradio-filter volk) 79 | target_include_directories(gnuradio-lfast 80 | PUBLIC $ 81 | PUBLIC $ 82 | ) 83 | set_target_properties(gnuradio-lfast PROPERTIES DEFINE_SYMBOL "gnuradio_lfast_EXPORTS") 84 | 85 | if(APPLE) 86 | set_target_properties(gnuradio-lfast PROPERTIES 87 | INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib" 88 | ) 89 | endif(APPLE) 90 | 91 | ######################################################################## 92 | # Install built library files 93 | ######################################################################## 94 | include(GrMiscUtils) 95 | GR_LIBRARY_FOO(gnuradio-lfast) 96 | 97 | ######################################################################## 98 | # Print summary 99 | ######################################################################## 100 | message(STATUS "Using install prefix: ${CMAKE_INSTALL_PREFIX}") 101 | message(STATUS "Building for version: ${VERSION} / ${LIBVER}") 102 | 103 | ######################################################################## 104 | # Build test command-line tool 105 | ######################################################################## 106 | include(GrTest) 107 | 108 | include_directories(${CPPUNIT_INCLUDE_DIRS}) 109 | 110 | list(APPEND test_lfast_sources 111 | ${CMAKE_CURRENT_SOURCE_DIR}/test_lfast.cc 112 | ${CMAKE_CURRENT_SOURCE_DIR}/costas2_impl.cc 113 | ${CMAKE_CURRENT_SOURCE_DIR}/costas4_impl.cc 114 | ${CMAKE_CURRENT_SOURCE_DIR}/agc_fast_impl.cc 115 | ${CMAKE_CURRENT_SOURCE_DIR}/CC2F2ByteVector_impl.cc 116 | ${CMAKE_CURRENT_SOURCE_DIR}/nlog10volk_impl.cc 117 | ${CMAKE_CURRENT_SOURCE_DIR}/quad_demod_volk_impl.cc 118 | ${CMAKE_CURRENT_SOURCE_DIR}/MTFIRFilterCCF_impl.cc 119 | ${CMAKE_CURRENT_SOURCE_DIR}/fir_filter_lfast.cc 120 | ) 121 | 122 | add_executable(test-lfast ${test_lfast_sources}) 123 | 124 | target_link_libraries( 125 | test-lfast 126 | ${GNURADIO_RUNTIME_LIBRARIES} 127 | ${Boost_LIBRARIES} 128 | boost_thread 129 | ${CPPUNIT_LIBRARIES} 130 | gnuradio-blocks 131 | gnuradio-filter 132 | volk 133 | gnuradio-lfast 134 | pthread 135 | ) 136 | 137 | install(TARGETS test-lfast DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" RUNTIME) 138 | 139 | -------------------------------------------------------------------------------- /lib/agc_fast_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 22 | #include "agc_fast_impl.h" 23 | #include 24 | #include "scomplex.h" 25 | 26 | // assisted detection of Fused Multiply Add (FMA) functionality 27 | #if !defined(__FMA__) && defined(__AVX2__) 28 | #define __FMA__ 1 29 | #endif 30 | 31 | #if defined(FP_FAST_FMA) 32 | #define __FMA__ 1 33 | #endif 34 | 35 | #if defined(__FMA__) 36 | #pragma message "FMA support detected. Compiling for Fused Multiply/Add support." 37 | #else 38 | #pragma message "No FMA support detected. Compiling for normal math." 39 | #endif 40 | 41 | namespace gr { 42 | namespace lfast { 43 | 44 | agc_fast::sptr agc_fast::make(float rate, float reference, float gain) 45 | { 46 | return gnuradio::make_block_sptr(rate, reference, gain); 47 | } 48 | 49 | /* 50 | * The private constructor 51 | */ 52 | agc_fast_impl::agc_fast_impl(float rate, float reference, float gain) 53 | : gr::sync_block("agc_fast", 54 | io_signature::make(1, 1, sizeof(gr_complex)), 55 | io_signature::make(1, 1, sizeof(gr_complex))), 56 | kernel::agc_cc(rate, reference, gain, 65536) 57 | { 58 | const int alignment_multiple = 59 | volk_get_alignment() / sizeof(gr_complex); 60 | set_alignment(std::max(1, alignment_multiple)); 61 | } 62 | 63 | /* 64 | * Our virtual destructor. 65 | */ 66 | agc_fast_impl::~agc_fast_impl() 67 | { 68 | } 69 | 70 | int 71 | agc_fast_impl::work_original(int noutput_items, 72 | gr_vector_const_void_star &input_items, 73 | gr_vector_void_star &output_items) 74 | { 75 | const gr_complex *in = (const gr_complex*)input_items[0]; 76 | gr_complex *out = (gr_complex*)output_items[0]; 77 | scaleN(out, in, noutput_items); 78 | return noutput_items; 79 | } 80 | int 81 | agc_fast_impl::work_test(int noutput_items, 82 | gr_vector_const_void_star &input_items, 83 | gr_vector_void_star &output_items) 84 | { 85 | const gr_complex *in = (const gr_complex*)input_items[0]; 86 | gr_complex *out = (gr_complex*)output_items[0]; 87 | StructComplex *sOut = (StructComplex*)output_items[0]; 88 | 89 | float o_i,o_r; 90 | /* 91 | union 92 | { 93 | int i; 94 | float x; 95 | } u; 96 | */ 97 | float val,sqrt_val; 98 | int *i_ptr; 99 | 100 | for (int i=0;i> 1) - (1<<22); 114 | sqrt_val = sqrt_val + val/sqrt_val; 115 | sqrt_val = _reference - 0.25f*sqrt_val + val/sqrt_val; 116 | 117 | // _gain += _rate * sqrt_val; 118 | */ 119 | 120 | #if defined(__FMA__) 121 | _gain = _gain + _rate * (_reference - sqrt(__builtin_fmaf(o_r,o_r,o_i*o_i))); 122 | #else 123 | _gain = _gain + _rate * (_reference - sqrt(o_r*o_r + o_i*o_i)); 124 | #endif 125 | 126 | if(_max_gain > 0.0 && _gain > _max_gain) { 127 | _gain = _max_gain; 128 | } 129 | 130 | } 131 | return noutput_items; 132 | } 133 | 134 | int 135 | agc_fast_impl::work(int noutput_items, 136 | gr_vector_const_void_star &input_items, 137 | gr_vector_void_star &output_items) 138 | { 139 | const gr_complex *in = (const gr_complex*)input_items[0]; 140 | gr_complex *out = (gr_complex*)output_items[0]; 141 | StructComplex *sOut = (StructComplex*)output_items[0]; 142 | 143 | float o_i,o_r; 144 | /* 145 | union 146 | { 147 | int i; 148 | float x; 149 | } u; 150 | */ 151 | float val,sqrt_val; 152 | int *i_ptr; 153 | 154 | for (int i=0;i> 1) - (1<<22); 168 | sqrt_val = sqrt_val + val/sqrt_val; 169 | sqrt_val = _reference - 0.25f*sqrt_val + val/sqrt_val; 170 | 171 | // _gain += _rate * sqrt_val; 172 | */ 173 | 174 | #if defined(__FMA__) 175 | _gain = _gain + _rate * (_reference - sqrt(__builtin_fmaf(o_r,o_r,o_i*o_i))); 176 | #else 177 | _gain = _gain + _rate * (_reference - sqrt(o_r*o_r + o_i*o_i)); 178 | #endif 179 | 180 | if(_max_gain > 0.0 && _gain > _max_gain) { 181 | _gain = _max_gain; 182 | } 183 | 184 | } 185 | return noutput_items; 186 | } 187 | } /* namespace lfast */ 188 | } /* namespace gr */ 189 | 190 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /examples/lfast_Test-Filter.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: test_lfastfilter 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | window_size: '' 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: cutoff_freq 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: 3e6 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [416, 20] 46 | rotation: 0 47 | state: enabled 48 | - name: samp_rate 49 | id: variable 50 | parameters: 51 | comment: '' 52 | value: 10.7622e6 53 | states: 54 | bus_sink: false 55 | bus_source: false 56 | bus_structure: null 57 | coordinate: [16, 92] 58 | rotation: 0 59 | state: enabled 60 | - name: blocks_file_source_0 61 | id: blocks_file_source 62 | parameters: 63 | affinity: '' 64 | alias: '' 65 | begin_tag: pmt.PMT_NIL 66 | comment: '' 67 | file: /opt/sdr/gnuradio/gnuradio_recordings/atsc/gnuradio_atsc_593MHz_6.2MSPS.raw 68 | length: '0' 69 | maxoutbuf: '0' 70 | minoutbuf: '0' 71 | offset: '0' 72 | repeat: 'True' 73 | type: complex 74 | vlen: '1' 75 | states: 76 | bus_sink: false 77 | bus_source: false 78 | bus_structure: null 79 | coordinate: [104, 252] 80 | rotation: 0 81 | state: enabled 82 | - name: blocks_throttle_0 83 | id: blocks_throttle 84 | parameters: 85 | affinity: '' 86 | alias: '' 87 | comment: '' 88 | ignoretag: 'True' 89 | maxoutbuf: '0' 90 | minoutbuf: '0' 91 | samples_per_second: samp_rate 92 | type: complex 93 | vlen: '1' 94 | states: 95 | bus_sink: false 96 | bus_source: false 97 | bus_structure: null 98 | coordinate: [352, 260] 99 | rotation: 0 100 | state: enabled 101 | - name: import_0 102 | id: import 103 | parameters: 104 | alias: '' 105 | comment: '' 106 | imports: from gnuradio.fft import window 107 | states: 108 | bus_sink: false 109 | bus_source: false 110 | bus_structure: null 111 | coordinate: [352, 112.0] 112 | rotation: 0 113 | state: true 114 | - name: lfast_MTFIRLowPassFilterXX_0 115 | id: lfast_MTFIRLowPassFilterXX 116 | parameters: 117 | affinity: '' 118 | alias: '' 119 | beta: '6.76' 120 | comment: '' 121 | cutoff_freq: cutoff_freq 122 | gain: '1' 123 | maxoutbuf: '0' 124 | minoutbuf: '0' 125 | nthreads: '4' 126 | samp_rate: samp_rate 127 | type: CCF 128 | width: cutoff_freq*.2 129 | win: window.WIN_HAMMING 130 | states: 131 | bus_sink: false 132 | bus_source: false 133 | bus_structure: null 134 | coordinate: [624, 468] 135 | rotation: 0 136 | state: enabled 137 | - name: low_pass_filter_0 138 | id: low_pass_filter 139 | parameters: 140 | affinity: '' 141 | alias: '' 142 | beta: '6.76' 143 | comment: '' 144 | cutoff_freq: cutoff_freq 145 | decim: '1' 146 | gain: '1' 147 | interp: '1' 148 | maxoutbuf: '0' 149 | minoutbuf: '0' 150 | samp_rate: samp_rate 151 | type: fir_filter_ccf 152 | width: cutoff_freq*.2 153 | win: window.WIN_HAMMING 154 | states: 155 | bus_sink: false 156 | bus_source: false 157 | bus_structure: null 158 | coordinate: [648, 288] 159 | rotation: 0 160 | state: enabled 161 | - name: qtgui_freq_sink_x_0 162 | id: qtgui_freq_sink_x 163 | parameters: 164 | affinity: '' 165 | alias: '' 166 | alpha1: '1.0' 167 | alpha10: '1.0' 168 | alpha2: '1.0' 169 | alpha3: '1.0' 170 | alpha4: '1.0' 171 | alpha5: '1.0' 172 | alpha6: '1.0' 173 | alpha7: '1.0' 174 | alpha8: '1.0' 175 | alpha9: '1.0' 176 | autoscale: 'False' 177 | average: '1.0' 178 | axislabels: 'True' 179 | bw: samp_rate 180 | color1: '"green"' 181 | color10: '"dark blue"' 182 | color2: '"blue"' 183 | color3: '"red"' 184 | color4: '"black"' 185 | color5: '"cyan"' 186 | color6: '"magenta"' 187 | color7: '"yellow"' 188 | color8: '"dark red"' 189 | color9: '"dark green"' 190 | comment: '' 191 | ctrlpanel: 'False' 192 | fc: 593e6 193 | fftsize: '1024' 194 | freqhalf: 'True' 195 | grid: 'False' 196 | gui_hint: '' 197 | label: Relative Gain 198 | label1: Raw 199 | label10: '' 200 | label2: GNURadio 201 | label3: LFast 202 | label4: '' 203 | label5: '' 204 | label6: '' 205 | label7: '' 206 | label8: '' 207 | label9: '' 208 | legend: 'True' 209 | maxoutbuf: '0' 210 | minoutbuf: '0' 211 | name: '"Filtered Signal"' 212 | nconnections: '3' 213 | norm_window: 'False' 214 | showports: 'True' 215 | tr_chan: '0' 216 | tr_level: '0.0' 217 | tr_mode: qtgui.TRIG_MODE_FREE 218 | tr_tag: '""' 219 | type: complex 220 | units: dB 221 | update_time: '0.10' 222 | width1: '1' 223 | width10: '1' 224 | width2: '1' 225 | width3: '1' 226 | width4: '1' 227 | width5: '1' 228 | width6: '1' 229 | width7: '1' 230 | width8: '1' 231 | width9: '1' 232 | wintype: window.WIN_BLACKMAN_hARRIS 233 | ymax: '10' 234 | ymin: '-140' 235 | states: 236 | bus_sink: false 237 | bus_source: false 238 | bus_structure: null 239 | coordinate: [976, 260] 240 | rotation: 0 241 | state: enabled 242 | 243 | connections: 244 | - [blocks_file_source_0, '0', blocks_throttle_0, '0'] 245 | - [blocks_throttle_0, '0', lfast_MTFIRLowPassFilterXX_0, '0'] 246 | - [blocks_throttle_0, '0', low_pass_filter_0, '0'] 247 | - [blocks_throttle_0, '0', qtgui_freq_sink_x_0, '0'] 248 | - [lfast_MTFIRLowPassFilterXX_0, '0', qtgui_freq_sink_x_0, '2'] 249 | - [low_pass_filter_0, '0', qtgui_freq_sink_x_0, '1'] 250 | 251 | metadata: 252 | file_format: 1 253 | grc_version: v3.11.0.0git-70-gf44384ae 254 | -------------------------------------------------------------------------------- /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-lfast 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gr-lfast - Timed, tuned, and accelerated GNURadio blocks 2 | 3 | ## Overview 4 | The goal of the gr-lfast project is to increase flowgraph performance while running on a general purpose CPU. So far the project uses several techniques to achieve the performance boosts: 5 | 6 | 1. No algorithm changes are made, but common C++ optimization techniques could be applied to increase overall throughput. 7 | 2. Block consolidation at the code level rather than a hierarchical block (reusing variables and buffers without needing to recreate per block). 8 | 3. Fused Multiply/Add CPU execution when supported. 9 | 3. Multi-threading is used where possible (FIR filters for example). 10 | 4. For filters, the OpenCL gr-clenabled project timing study called out that the GNURadio FFT filters are faster in some instances compared to the FIR versions. However the standard convenience wrappers for low pass, high pass, and root-raised cosine among others are using the FIR filters. Therefore convenience wrappers around the FFT equivalents are included here as well. 11 | 12 | ## Included Blocks 13 | 14 | 1. Costas Loop (2nd and 4th Orders) 15 | 2. AGC Control (Complex and Float) 16 | 3. FFT-based Low Pass Filter Convenience Wrapper 17 | 4. FFT-based High Pass Filter Convenience Wrapper 18 | 5. FFT-based Root Raised Cosine Filter Convenience Wrapper 19 | 6. Aggregated block that does Complex to Real->Byte->Vector in a single C++ implementation 20 | 21 | 7. Log Block (n*log10(x) + k) implemented with Volk [Note that as of GNU Radio 3.8, the volk approach is now in the standard block] 22 | 8. Multi-threaded FIR filters 23 | 24 | ## Command-line tools 25 | 26 | The project includes a command-line tool called test-lfast which will provide timing on the non-filter blocks. The timing output shows the original GNURadio block throughput along with the new optimized throughput on your specific hardware. Since so many factors can go into the resulting timing, it's a good idea to run this on the specific system you'll be using the blocks on. 27 | 28 | ## Building 29 | gr-lfast is available in the pybombs repository. However to build gr-lfast from source, simply follow the standard module build process. Git clone it to a directory, close GNURadio if you have it open, then use the following build steps: 30 | 31 | cd 32 | 33 | mkdir build 34 | 35 | cd build 36 | 37 | cmake .. 38 | 39 | make 40 | 41 | [sudo] make install 42 | 43 | sudo ldconfig 44 | 45 | If each step was successful (do not overlook the "sudo ldconfig" step). 46 | 47 | ## Details 48 | In terms of code optimization, gr-lfast focuses on using basic C++ code optimization techniques such as eliminating stack pushes associated with function jumps, Fused Multiply/Add (FMA) operations if the CPU supports it in hardware, eliminating unnecessary loops, and other techniques to increase overall throughput without the need to rewrite any of the signal processing algorithms themselves. 49 | 50 | For instance the native 2nd order Costas Loop module running on an i7-6700 clocked at processing about 22.2 Msps. After optimizing the code 51 | the 2nd order loop was capable of processing almost 38 Msps (a 71% speed increase). A 4th order loop went from about 21.8 Msps to almost 33 Msps (a 50.6% improvement). 52 | 53 | The same approach was applied to the AGC block for about a 17-20% speed increase to about 104 MSPS. 54 | 55 | The block Complex->Real->Char->Vector combines Complex->Real, Float->char, and stream->Vector in a single block, saving on buffer copies 56 | and multiple threads. Overall speedup on that block was nominal, 2-3%. 57 | 58 | Note there is a significant speed increase in log calculations with some math refactoring to take advantage of a volk log2 function to calculate the log10 (n*log10(x) = n*log10(x) as n*log2(x)/log2(10) = (n/log2(10)) * log2(x)). This resulted in a 350% speed increase. 59 | 60 | FIR filters were also optimized to take advantage of multi-threading. The test-lfast tool can be used as shown below to determine the optimal number of threads given your CPU and number of taps. Generally 3-4 threads is a good place to be. 61 | 62 | The plan is to add more blocks as I run into needing them. 63 | 64 | The following output from running 'test-lfast' shows the speed increases on a newer laptop with an Intel i7-7700HQ 7th Gen processor. 65 | 66 | Testing 2nd order Costas Loop with 8,192 samples... 67 | Original Code Run Time: 0.000544 s (15,054,931.000000 sps) 68 | LFAST Code Run Time: 0.000202 s (40,552,132.000000 sps) 69 | Speedup: 169.36% faster 70 | 71 | Testing 4th order Costas Loop with 8,192 samples... 72 | Original Code Run Time: 0.000373 s (21,946,850.000000 sps) 73 | LFAST Code Run Time: 0.000240 s (34,098,004.000000 sps) 74 | Speedup: 55.37% faster 75 | 76 | ---------------------------------------------------------- 77 | Testing AGC with 8,192 samples... 78 | Original Code Run Time: 0.000093 s (87,887,608.000000 sps) 79 | LFAST Code Run Time: 0.000075 s (109,181,128.000000 sps) 80 | Speedup: 24.23% faster 81 | 82 | ---------------------------------------------------------- 83 | Testing Complex->Real->Char->Vector with 8,192 samples... 84 | Original Code Run Time: 0.000007 s (1,207,321,088.000000 sps) 85 | LFAST Code Run Time: 0.000007 s (1,242,644,864.000000 sps) 86 | Speedup: 2.93% faster 87 | 88 | ---------------------------------------------------------- 89 | Testing volk nlog10+k with 8,192 samples... 90 | Original Code Run Time: 0.000135 s (60,607,308.000000 sps) 91 | LFAST Code Run Time: 0.000041 s (199,728,688.000000 sps) 92 | Speedup: 229.55% faster 93 | 94 | ---------------------------------------------------------- 95 | Testing FIR filter with complex data and float taps with 241 taps, 8,192 samples... 96 | Original Code Run Time: 0.000447 s (18,344,648.000000 sps) 97 | LFAST Code Run Time [1 threads]: 0.000646 s (12,673,606.000000 sps) 98 | 1-thread Speedup: -30.91% faster 99 | LFAST Code Run Time [2 threads]: 0.000287 s (28,563,974.000000 sps) 100 | 2-thread Speedup: 55.71% faster 101 | LFAST Code Run Time [3 threads]: 0.000294 s (27,822,952.000000 sps) 102 | 3-thread Speedup: 51.67% faster 103 | LFAST Code Run Time [4 threads]: 0.000268 s (30,516,536.000000 sps) 104 | 4-thread Speedup: 66.35% faster 105 | LFAST Code Run Time [5 threads]: 0.000347 s (23,585,654.000000 sps) 106 | 5-thread Speedup: 28.57% faster 107 | LFAST Code Run Time [6 threads]: 0.000291 s (28,183,880.000000 sps) 108 | 6-thread Speedup: 53.64% faster 109 | LFAST Code Run Time [7 threads]: 0.000386 s (21,199,370.000000 sps) 110 | 7-thread Speedup: 15.56% faster 111 | LFAST Code Run Time [8 threads]: 0.000339 s (24,150,214.000000 sps) 112 | 8-thread Speedup: 31.65% faster 113 | 114 | Fastest filter thread performance: 115 | Number of Samples in test case (can be varied with command-line parameter): 8,192 116 | Number of taps in filter (can be varied with command-line parameter): 241 117 | Fastest Thread Count: 4 118 | Original SPS: 18,344,648.00 119 | Fastest SPS: 30,516,536.00 120 | Speedup: 66.35% faster 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /examples/lfast_Test-Filter-decimating.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: test_lfastfilterdecim 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | window_size: '' 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: cutoff_freq 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: 3e6 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [416, 20] 46 | rotation: 0 47 | state: enabled 48 | - name: decimatedRate 49 | id: variable 50 | parameters: 51 | comment: '' 52 | value: int(samp_rate/decimation) 53 | states: 54 | bus_sink: false 55 | bus_source: false 56 | bus_structure: null 57 | coordinate: [712, 28] 58 | rotation: 0 59 | state: enabled 60 | - name: decimation 61 | id: variable 62 | parameters: 63 | comment: '' 64 | value: '4' 65 | states: 66 | bus_sink: false 67 | bus_source: false 68 | bus_structure: null 69 | coordinate: [568, 28] 70 | rotation: 0 71 | state: enabled 72 | - name: samp_rate 73 | id: variable 74 | parameters: 75 | comment: '' 76 | value: 10.7622e6 77 | states: 78 | bus_sink: false 79 | bus_source: false 80 | bus_structure: null 81 | coordinate: [16, 92] 82 | rotation: 0 83 | state: enabled 84 | - name: blocks_file_source_0 85 | id: blocks_file_source 86 | parameters: 87 | affinity: '' 88 | alias: '' 89 | begin_tag: pmt.PMT_NIL 90 | comment: '' 91 | file: /opt/sdr/gnuradio/gnuradio_recordings/atsc/atsctest.cfile 92 | length: '0' 93 | maxoutbuf: '0' 94 | minoutbuf: '0' 95 | offset: '0' 96 | repeat: 'True' 97 | type: complex 98 | vlen: '1' 99 | states: 100 | bus_sink: false 101 | bus_source: false 102 | bus_structure: null 103 | coordinate: [104, 252] 104 | rotation: 0 105 | state: enabled 106 | - name: blocks_throttle_0 107 | id: blocks_throttle 108 | parameters: 109 | affinity: '' 110 | alias: '' 111 | comment: '' 112 | ignoretag: 'True' 113 | maxoutbuf: '0' 114 | minoutbuf: '0' 115 | samples_per_second: samp_rate 116 | type: complex 117 | vlen: '1' 118 | states: 119 | bus_sink: false 120 | bus_source: false 121 | bus_structure: null 122 | coordinate: [352, 260] 123 | rotation: 0 124 | state: enabled 125 | - name: lfast_MTFIRLowPassFilterXX_0 126 | id: lfast_MTFIRLowPassFilterXX 127 | parameters: 128 | affinity: '' 129 | alias: '' 130 | beta: '6.76' 131 | comment: '' 132 | cutoff_freq: cutoff_freq 133 | gain: '1' 134 | maxoutbuf: '0' 135 | minoutbuf: '8192' 136 | nthreads: '1' 137 | samp_rate: samp_rate 138 | type: CCF 139 | width: cutoff_freq*.2 140 | win: window.WIN_HAMMING 141 | states: 142 | bus_sink: false 143 | bus_source: false 144 | bus_structure: null 145 | coordinate: [624, 468] 146 | rotation: 0 147 | state: enabled 148 | - name: low_pass_filter_0 149 | id: low_pass_filter 150 | parameters: 151 | affinity: '' 152 | alias: '' 153 | beta: '6.76' 154 | comment: '' 155 | cutoff_freq: cutoff_freq 156 | decim: decimation 157 | gain: '1' 158 | interp: '1' 159 | maxoutbuf: '0' 160 | minoutbuf: '0' 161 | samp_rate: samp_rate 162 | type: fir_filter_ccf 163 | width: cutoff_freq*.2 164 | win: window.WIN_HAMMING 165 | states: 166 | bus_sink: false 167 | bus_source: false 168 | bus_structure: null 169 | coordinate: [648, 288] 170 | rotation: 0 171 | state: enabled 172 | - name: qtgui_freq_sink_x_0 173 | id: qtgui_freq_sink_x 174 | parameters: 175 | affinity: '' 176 | alias: '' 177 | alpha1: '1.0' 178 | alpha10: '1.0' 179 | alpha2: '1.0' 180 | alpha3: '1.0' 181 | alpha4: '1.0' 182 | alpha5: '1.0' 183 | alpha6: '1.0' 184 | alpha7: '1.0' 185 | alpha8: '1.0' 186 | alpha9: '1.0' 187 | autoscale: 'False' 188 | average: '1.0' 189 | axislabels: 'True' 190 | bw: decimatedRate 191 | color1: '"green"' 192 | color10: '"dark blue"' 193 | color2: '"blue"' 194 | color3: '"red"' 195 | color4: '"black"' 196 | color5: '"cyan"' 197 | color6: '"magenta"' 198 | color7: '"yellow"' 199 | color8: '"dark red"' 200 | color9: '"dark green"' 201 | comment: '' 202 | ctrlpanel: 'False' 203 | fc: 593e6 204 | fftsize: '1024' 205 | freqhalf: 'True' 206 | grid: 'False' 207 | gui_hint: '' 208 | label: Relative Gain 209 | label1: Raw 210 | label10: '' 211 | label2: GNURadio 212 | label3: LFast 213 | label4: '' 214 | label5: '' 215 | label6: '' 216 | label7: '' 217 | label8: '' 218 | label9: '' 219 | legend: 'True' 220 | maxoutbuf: '0' 221 | minoutbuf: '0' 222 | name: '"Filtered Signal"' 223 | nconnections: '3' 224 | norm_window: 'False' 225 | showports: 'True' 226 | tr_chan: '0' 227 | tr_level: '0.0' 228 | tr_mode: qtgui.TRIG_MODE_FREE 229 | tr_tag: '""' 230 | type: complex 231 | units: dB 232 | update_time: '0.10' 233 | width1: '1' 234 | width10: '1' 235 | width2: '1' 236 | width3: '1' 237 | width4: '1' 238 | width5: '1' 239 | width6: '1' 240 | width7: '1' 241 | width8: '1' 242 | width9: '1' 243 | wintype: window.WIN_BLACKMAN_hARRIS 244 | ymax: '10' 245 | ymin: '-140' 246 | states: 247 | bus_sink: false 248 | bus_source: false 249 | bus_structure: null 250 | coordinate: [976, 260] 251 | rotation: 0 252 | state: enabled 253 | - name: rational_resampler_xxx_0 254 | id: rational_resampler_xxx 255 | parameters: 256 | affinity: '' 257 | alias: '' 258 | comment: '' 259 | decim: decimation 260 | fbw: '0' 261 | interp: '1' 262 | maxoutbuf: '0' 263 | minoutbuf: '0' 264 | taps: '' 265 | type: ccc 266 | states: 267 | bus_sink: false 268 | bus_source: false 269 | bus_structure: null 270 | coordinate: [696, 176] 271 | rotation: 0 272 | state: enabled 273 | 274 | connections: 275 | - [blocks_file_source_0, '0', blocks_throttle_0, '0'] 276 | - [blocks_throttle_0, '0', lfast_MTFIRLowPassFilterXX_0, '0'] 277 | - [blocks_throttle_0, '0', low_pass_filter_0, '0'] 278 | - [blocks_throttle_0, '0', rational_resampler_xxx_0, '0'] 279 | - [lfast_MTFIRLowPassFilterXX_0, '0', qtgui_freq_sink_x_0, '2'] 280 | - [low_pass_filter_0, '0', qtgui_freq_sink_x_0, '1'] 281 | - [rational_resampler_xxx_0, '0', qtgui_freq_sink_x_0, '0'] 282 | 283 | metadata: 284 | file_format: 1 285 | grc_version: v3.11.0.0git-70-gf44384ae 286 | -------------------------------------------------------------------------------- /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-lfast 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-lfast 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 | # Install directories 87 | ######################################################################## 88 | include(FindPkgConfig) 89 | find_package(Gnuradio "3.9" REQUIRED) 90 | include(GrVersion) 91 | 92 | include(GrPlatform) #define LIB_SUFFIX 93 | 94 | if(NOT CMAKE_MODULES_DIR) 95 | set(CMAKE_MODULES_DIR lib${LIB_SUFFIX}/cmake) 96 | endif(NOT CMAKE_MODULES_DIR) 97 | 98 | set(GR_INCLUDE_DIR include/lfast) 99 | set(GR_CMAKE_DIR ${CMAKE_MODULES_DIR}/lfast) 100 | set(GR_PKG_DATA_DIR ${GR_DATA_DIR}/${CMAKE_PROJECT_NAME}) 101 | set(GR_PKG_DOC_DIR ${GR_DOC_DIR}/${CMAKE_PROJECT_NAME}) 102 | set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) 103 | set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) 104 | 105 | ######################################################################## 106 | # On Apple only, set install name and use rpath correctly, if not already set 107 | ######################################################################## 108 | if(APPLE) 109 | if(NOT CMAKE_INSTALL_NAME_DIR) 110 | set(CMAKE_INSTALL_NAME_DIR 111 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 112 | PATH "Library Install Name Destination Directory" FORCE) 113 | endif(NOT CMAKE_INSTALL_NAME_DIR) 114 | if(NOT CMAKE_INSTALL_RPATH) 115 | set(CMAKE_INSTALL_RPATH 116 | ${CMAKE_INSTALL_PREFIX}/${GR_LIBRARY_DIR} CACHE 117 | PATH "Library Install RPath" FORCE) 118 | endif(NOT CMAKE_INSTALL_RPATH) 119 | if(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 120 | set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE 121 | BOOL "Do Build Using Library Install RPath" FORCE) 122 | endif(NOT CMAKE_BUILD_WITH_INSTALL_RPATH) 123 | endif(APPLE) 124 | 125 | ######################################################################## 126 | # Find gnuradio build dependencies 127 | ######################################################################## 128 | find_package(Doxygen) 129 | 130 | ######################################################################## 131 | # PyBind11 Related 132 | ######################################################################## 133 | 134 | find_package(pybind11 REQUIRED) 135 | execute_process( 136 | COMMAND "${PYTHON_EXECUTABLE}" -c 137 | "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" 138 | OUTPUT_VARIABLE PYTHON_NUMPY_INCLUDE_DIR) 139 | 140 | ######################################################################## 141 | # Setup doxygen option 142 | ######################################################################## 143 | if(DOXYGEN_FOUND) 144 | option(ENABLE_DOXYGEN "Build docs using Doxygen" ON) 145 | else(DOXYGEN_FOUND) 146 | option(ENABLE_DOXYGEN "Build docs using Doxygen" OFF) 147 | endif(DOXYGEN_FOUND) 148 | 149 | ######################################################################## 150 | # Create uninstall target 151 | ######################################################################## 152 | configure_file( 153 | ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in 154 | ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 155 | @ONLY) 156 | 157 | add_custom_target(uninstall 158 | ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake 159 | ) 160 | 161 | 162 | ######################################################################## 163 | # Add subdirectories 164 | ######################################################################## 165 | add_subdirectory(include/lfast) 166 | add_subdirectory(lib) 167 | add_subdirectory(apps) 168 | add_subdirectory(docs) 169 | # NOTE: manually update below to use GRC to generate C++ flowgraphs w/o python 170 | if(ENABLE_PYTHON) 171 | message(STATUS "PYTHON and GRC components are enabled") 172 | add_subdirectory(python) 173 | add_subdirectory(grc) 174 | else(ENABLE_PYTHON) 175 | message(STATUS "PYTHON and GRC components are disabled") 176 | endif(ENABLE_PYTHON) 177 | 178 | ######################################################################## 179 | # Install cmake search helper for this library 180 | ######################################################################## 181 | 182 | install(FILES cmake/Modules/lfastConfig.cmake 183 | DESTINATION ${CMAKE_MODULES_DIR}/lfast 184 | ) 185 | -------------------------------------------------------------------------------- /examples/rotator_test.grc: -------------------------------------------------------------------------------- 1 | options: 2 | parameters: 3 | author: '' 4 | catch_exceptions: 'True' 5 | category: '[GRC Hier Blocks]' 6 | cmake_opt: '' 7 | comment: '' 8 | copyright: '' 9 | description: '' 10 | gen_cmake: 'On' 11 | gen_linking: dynamic 12 | generate_options: qt_gui 13 | hier_block_src_path: '.:' 14 | id: test_rotator 15 | max_nouts: '0' 16 | output_language: python 17 | placement: (0,0) 18 | qt_qss_theme: '' 19 | realtime_scheduling: '' 20 | run: 'True' 21 | run_command: '{python} -u {filename}' 22 | run_options: prompt 23 | sizing_mode: fixed 24 | thread_safe_setters: '' 25 | title: '' 26 | window_size: '' 27 | states: 28 | bus_sink: false 29 | bus_source: false 30 | bus_structure: null 31 | coordinate: [8, 8] 32 | rotation: 0 33 | state: enabled 34 | 35 | blocks: 36 | - name: center_freq 37 | id: variable 38 | parameters: 39 | comment: '' 40 | value: 162.425e6 41 | states: 42 | bus_sink: false 43 | bus_source: false 44 | bus_structure: null 45 | coordinate: [432, 20] 46 | rotation: 0 47 | state: enabled 48 | - name: offset 49 | id: variable_qtgui_range 50 | parameters: 51 | comment: '' 52 | gui_hint: 0,0,1,3 53 | label: '' 54 | min_len: '200' 55 | orient: QtCore.Qt.Horizontal 56 | rangeType: float 57 | start: '0' 58 | step: 50e3 59 | stop: 800e3 60 | value: 500e3 61 | widget: counter_slider 62 | states: 63 | bus_sink: false 64 | bus_source: false 65 | bus_structure: null 66 | coordinate: [584, 8] 67 | rotation: 0 68 | state: enabled 69 | - name: samp_rate 70 | id: variable 71 | parameters: 72 | comment: '' 73 | value: 600e3 74 | states: 75 | bus_sink: false 76 | bus_source: false 77 | bus_structure: null 78 | coordinate: [8, 160] 79 | rotation: 0 80 | state: enabled 81 | - name: analog_sig_source_x_0 82 | id: analog_sig_source_x 83 | parameters: 84 | affinity: '' 85 | alias: '' 86 | amp: '1' 87 | comment: '' 88 | freq: offset 89 | maxoutbuf: '0' 90 | minoutbuf: '0' 91 | offset: '0' 92 | phase: '0' 93 | samp_rate: samp_rate 94 | type: complex 95 | waveform: analog.GR_COS_WAVE 96 | states: 97 | bus_sink: false 98 | bus_source: false 99 | bus_structure: null 100 | coordinate: [368, 472] 101 | rotation: 0 102 | state: enabled 103 | - name: blocks_multiply_xx_0 104 | id: blocks_multiply_xx 105 | parameters: 106 | affinity: '' 107 | alias: '' 108 | comment: '' 109 | maxoutbuf: '0' 110 | minoutbuf: '0' 111 | num_inputs: '2' 112 | type: complex 113 | vlen: '1' 114 | states: 115 | bus_sink: false 116 | bus_source: false 117 | bus_structure: null 118 | coordinate: [616, 432] 119 | rotation: 0 120 | state: enabled 121 | - name: blocks_rotator_cc_0 122 | id: blocks_rotator_cc 123 | parameters: 124 | affinity: '' 125 | alias: '' 126 | comment: '' 127 | maxoutbuf: '0' 128 | minoutbuf: '0' 129 | phase_inc: 2*math.pi*(offset)/samp_rate 130 | tag_inc_update: 'False' 131 | states: 132 | bus_sink: false 133 | bus_source: false 134 | bus_structure: null 135 | coordinate: [568, 308] 136 | rotation: 0 137 | state: enabled 138 | - name: blocks_throttle_0 139 | id: blocks_throttle 140 | parameters: 141 | affinity: '' 142 | alias: '' 143 | comment: '' 144 | ignoretag: 'True' 145 | maxoutbuf: '0' 146 | minoutbuf: '0' 147 | samples_per_second: samp_rate 148 | type: complex 149 | vlen: '1' 150 | states: 151 | bus_sink: false 152 | bus_source: false 153 | bus_structure: null 154 | coordinate: [312, 316] 155 | rotation: 0 156 | state: enabled 157 | - name: filerepeater_file_repeater_ex_0 158 | id: filerepeater_file_repeater_ex 159 | parameters: 160 | affinity: '' 161 | alias: '' 162 | comment: '' 163 | complexconv: '0' 164 | delayFirstStart: '0.0' 165 | file: /opt/sdr/gnuradio/gnuradio_recordings/NOAA_weather_radio_162.425MHz_NBFM_600KSPS_NoFilter.iq 166 | maxoutbuf: '0' 167 | minoutbuf: '0' 168 | repeat: 'True' 169 | repeat_delay: '0' 170 | repeat_times: '0' 171 | type: complex 172 | verbose: 'False' 173 | vlen: '1' 174 | states: 175 | bus_sink: false 176 | bus_source: false 177 | bus_structure: null 178 | coordinate: [80, 272] 179 | rotation: 0 180 | state: enabled 181 | - name: import_0 182 | id: import 183 | parameters: 184 | alias: '' 185 | comment: '' 186 | imports: import math 187 | states: 188 | bus_sink: false 189 | bus_source: false 190 | bus_structure: null 191 | coordinate: [200, 12] 192 | rotation: 0 193 | state: enabled 194 | - name: lfast_freq_shift_0 195 | id: lfast_freq_shift 196 | parameters: 197 | affinity: '' 198 | alias: '' 199 | comment: '' 200 | freq: offset 201 | maxoutbuf: '0' 202 | minoutbuf: '0' 203 | sample_rate: samp_rate 204 | states: 205 | bus_sink: false 206 | bus_source: false 207 | bus_structure: null 208 | coordinate: [584, 364] 209 | rotation: 0 210 | state: enabled 211 | - name: qtgui_freq_sink_x_0 212 | id: qtgui_freq_sink_x 213 | parameters: 214 | affinity: '' 215 | alias: '' 216 | alpha1: '1.0' 217 | alpha10: '1.0' 218 | alpha2: '1.0' 219 | alpha3: '1.0' 220 | alpha4: '1.0' 221 | alpha5: '1.0' 222 | alpha6: '1.0' 223 | alpha7: '1.0' 224 | alpha8: '1.0' 225 | alpha9: '1.0' 226 | autoscale: 'False' 227 | average: '1.0' 228 | axislabels: 'True' 229 | bw: samp_rate 230 | color1: '"blue"' 231 | color10: '"dark blue"' 232 | color2: '"red"' 233 | color3: '"green"' 234 | color4: '"black"' 235 | color5: '"cyan"' 236 | color6: '"magenta"' 237 | color7: '"yellow"' 238 | color8: '"dark red"' 239 | color9: '"dark green"' 240 | comment: '' 241 | ctrlpanel: 'False' 242 | fc: center_freq 243 | fftsize: '1024' 244 | freqhalf: 'True' 245 | grid: 'False' 246 | gui_hint: 1,0,1,3 247 | label: Relative Gain 248 | label1: Rotator 249 | label10: '' 250 | label2: Mixer 251 | label3: Convenience Wrapper 252 | label4: '' 253 | label5: '' 254 | label6: '' 255 | label7: '' 256 | label8: '' 257 | label9: '' 258 | legend: 'True' 259 | maxoutbuf: '0' 260 | minoutbuf: '0' 261 | name: '""' 262 | nconnections: '3' 263 | norm_window: 'False' 264 | showports: 'True' 265 | tr_chan: '0' 266 | tr_level: '0.0' 267 | tr_mode: qtgui.TRIG_MODE_FREE 268 | tr_tag: '""' 269 | type: complex 270 | units: dB 271 | update_time: '0.10' 272 | width1: '1' 273 | width10: '1' 274 | width2: '1' 275 | width3: '1' 276 | width4: '1' 277 | width5: '1' 278 | width6: '1' 279 | width7: '1' 280 | width8: '1' 281 | width9: '1' 282 | wintype: window.WIN_BLACKMAN_hARRIS 283 | ymax: '10' 284 | ymin: '-140' 285 | states: 286 | bus_sink: false 287 | bus_source: false 288 | bus_structure: null 289 | coordinate: [976, 316] 290 | rotation: 0 291 | state: enabled 292 | 293 | connections: 294 | - [analog_sig_source_x_0, '0', blocks_multiply_xx_0, '1'] 295 | - [blocks_multiply_xx_0, '0', qtgui_freq_sink_x_0, '1'] 296 | - [blocks_rotator_cc_0, '0', qtgui_freq_sink_x_0, '0'] 297 | - [blocks_throttle_0, '0', blocks_multiply_xx_0, '0'] 298 | - [blocks_throttle_0, '0', blocks_rotator_cc_0, '0'] 299 | - [blocks_throttle_0, '0', lfast_freq_shift_0, '0'] 300 | - [filerepeater_file_repeater_ex_0, '0', blocks_throttle_0, '0'] 301 | - [lfast_freq_shift_0, '0', qtgui_freq_sink_x_0, '2'] 302 | 303 | metadata: 304 | file_format: 1 305 | grc_version: v3.11.0.0git-70-gf44384ae 306 | -------------------------------------------------------------------------------- /lib/CC2F2ByteVector_impl.cc: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | /* 3 | * Copyright 2017 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 22 | #include "CC2F2ByteVector_impl.h" 23 | #include 24 | #include "clSComplex.h" 25 | 26 | // concurrency function 27 | #include 28 | 29 | #define SLEEPTIME 6 30 | 31 | namespace gr { 32 | namespace lfast { 33 | 34 | CC2F2ByteVector::sptr CC2F2ByteVector::make(int scale, int vecLength, int numVecItems) 35 | { 36 | return gnuradio::make_block_sptr(scale, vecLength, numVecItems); 37 | } 38 | 39 | /* 40 | * The private constructor 41 | */ 42 | CC2F2ByteVector_impl::CC2F2ByteVector_impl(int scale,int vecLength,int numVecItems) 43 | : gr::sync_decimator("CC2F2ByteVector", 44 | gr::io_signature::make(1, 1, sizeof(gr_complex)*vecLength), 45 | gr::io_signature::make(1, 1, sizeof(char)*vecLength*numVecItems), 46 | numVecItems),d_scale(scale),d_vlen(vecLength) 47 | { 48 | const int alignment_multiple = volk_get_alignment() / sizeof(float); 49 | set_alignment(std::max(1,alignment_multiple)); 50 | 51 | int imaxItems=gr::block::max_noutput_items(); 52 | if (imaxItems==0) 53 | imaxItems=8192; 54 | 55 | setBufferLength(imaxItems); 56 | 57 | for (int i=0;isizeof_stream_item (0); 134 | 135 | // Have to adjust the number of items for testing. 136 | unsigned int noi = noutput_items; // block_size * noutput_items; 137 | 138 | // Complex to real 139 | float ftmp[noi]; 140 | 141 | volk_32fc_deinterleave_real_32f((float *)&ftmp[0], in, noi); 142 | 143 | // float/real to char 144 | char ctmp[noi]; 145 | volk_32f_s32f_convert_8i((int8_t *)&ctmp[0], &ftmp[0], d_scale, noi); 146 | 147 | // char to stream 148 | // memcpy (out, &ctmp, noutput_items * block_size); 149 | memcpy (out, &ctmp, noutput_items); 150 | 151 | return noutput_items; 152 | } 153 | 154 | 155 | int 156 | CC2F2ByteVector_impl::work_test(int noutput_items, 157 | gr_vector_const_void_star &input_items, 158 | gr_vector_void_star &output_items) 159 | { 160 | const gr_complex *in = (const gr_complex *) input_items[0]; 161 | char *out = (char *) output_items[0]; 162 | size_t block_size = output_signature()->sizeof_stream_item (0); 163 | unsigned int noi = noutput_items; // block_size * noutput_items; 164 | 165 | if (noi > curBufferSize) { 166 | setBufferLength(noi); 167 | } 168 | 169 | // Complex to real 170 | volk_32fc_deinterleave_real_32f(floatBuff, in, noi); 171 | 172 | // float/real to char and char to stream 173 | volk_32f_s32f_convert_8i((int8_t *)out, floatBuff, d_scale, noi); 174 | 175 | return noutput_items; 176 | } 177 | 178 | /* 179 | int 180 | CC2F2ByteVector_impl::work_test(int noutput_items, 181 | gr_vector_const_void_star &input_items, 182 | gr_vector_void_star &output_items) 183 | { 184 | gr::thread::scoped_lock guard(d_mutex); 185 | 186 | inBuffer = (const gr_complex *) input_items[0]; 187 | outBuffer = (char *) output_items[0]; 188 | // size_t block_size = output_signature()->sizeof_stream_item (0); 189 | // unsigned int numSamples = noutput_items; // block_size * noutput_items; 190 | 191 | if (noutput_items > curBufferSize) { 192 | setBufferLength(noutput_items); 193 | } 194 | 195 | int blockSize = noutput_items / concurentThreadsSupported; 196 | int lastBlock = noutput_items - (concurrentMinus1)*blockSize; 197 | 198 | for (int i=0;i0)) { 220 | volk_32fc_deinterleave_real_32f(&floatBuff[startIndex[threadIndex]], &inBuffer[startIndex[threadIndex]], threadBlockSize[threadIndex]); 221 | 222 | // float/real to char and char to stream 223 | volk_32f_s32f_convert_8i((int8_t *)&outBuffer[startIndex[threadIndex]], &floatBuff[startIndex[threadIndex]], d_scale, threadBlockSize[threadIndex]); 224 | dataReady[threadIndex] = false; 225 | } 226 | else { 227 | usleep(SLEEPTIME); 228 | } 229 | } 230 | } 231 | 232 | int 233 | CC2F2ByteVector_impl::work(int noutput_items, 234 | gr_vector_const_void_star &input_items, 235 | gr_vector_void_star &output_items) 236 | { 237 | const gr_complex *in = (const gr_complex *) input_items[0]; 238 | char *out = (char *) output_items[0]; 239 | size_t block_size = output_signature()->sizeof_stream_item (0); 240 | unsigned int noi = block_size * noutput_items; 241 | 242 | if (noi > curBufferSize) { 243 | setBufferLength(noi); 244 | } 245 | 246 | // Complex to real 247 | volk_32fc_deinterleave_real_32f(floatBuff, in, noi); 248 | 249 | // float/real to char and char to stream 250 | volk_32f_s32f_convert_8i((int8_t *)out, floatBuff, d_scale, noi); 251 | 252 | return noutput_items; 253 | } 254 | 255 | } /* namespace testtiming */ 256 | } /* namespace gr */ 257 | 258 | -------------------------------------------------------------------------------- /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-lfast 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 | -------------------------------------------------------------------------------- /lib/fir_filter_lfast.h: -------------------------------------------------------------------------------- 1 | /* 2 | * fir_filter_lfast.h 3 | * 4 | * Copyright 2019, Michael Piscopo 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | */ 19 | 20 | #ifndef INCLUDE_LFAST_FIR_FILTER_LFAST_H_ 21 | #define INCLUDE_LFAST_FIR_FILTER_LFAST_H_ 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | using namespace std; 28 | 29 | namespace gr { 30 | namespace lfast { 31 | /* 32 | * Base Filter 33 | */ 34 | template 35 | class Filter { 36 | protected: 37 | tap_type *alignedTaps; 38 | io_type *singlePointBuffer; 39 | std::vector d_taps; 40 | long numTaps; 41 | 42 | public: 43 | Filter(); 44 | Filter(const std::vector& newTaps); 45 | virtual ~Filter(); 46 | 47 | virtual void setTaps(const std::vector& newTaps); 48 | // For compatibility 49 | inline virtual void set_taps(const std::vector& newTaps) { setTaps(newTaps); }; 50 | virtual std::vector getTaps() const; 51 | inline virtual std::vector taps() const { return getTaps();}; 52 | inline virtual long ntaps() { return numTaps;}; 53 | 54 | // Returns number of samples consumed / produced 55 | virtual long filter(io_type *outputBuffer, const io_type *inputBuffer, long numSamples) {return 0;}; 56 | }; // end base filter template 57 | 58 | /* 59 | * FIR Filter - Complex inputs, float taps 60 | */ 61 | class FIRFilterCCF:public Filter { 62 | public: 63 | FIRFilterCCF(); 64 | FIRFilterCCF(const std::vector& newTaps); 65 | virtual ~FIRFilterCCF(); 66 | 67 | // NOTE: This routine is expecting numSamples to be an integer multiple of the number of taps 68 | virtual long filterN(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples); 69 | 70 | // OutputBuffer here should be at least numSamples/decimation in length 71 | virtual long filterNdec(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples, int decimation); 72 | 73 | virtual gr_complex filter(const gr_complex *inputBuffer); 74 | 75 | // This is for testing comparison. This function does all calculations in 1 CPU-based thread. 76 | virtual long filterCPU(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples); 77 | }; 78 | 79 | /* 80 | * FIR Filter - float inputs, float taps 81 | */ 82 | class FIRFilterFFF:public Filter { 83 | public: 84 | FIRFilterFFF(); 85 | FIRFilterFFF(const std::vector& newTaps); 86 | virtual ~FIRFilterFFF(); 87 | 88 | // NOTE: This routine is expecting numSamples to be an integer multiple of the number of taps 89 | virtual long filterN(float *outputBuffer, const float *inputBuffer, long numSamples); 90 | 91 | // OutputBuffer here should be at least numSamples/decimation in length 92 | virtual long filterNdec(float *outputBuffer, const float *inputBuffer, long numSamples, int decimation); 93 | 94 | virtual gr_complex filter(const float *inputBuffer); 95 | 96 | // This is for testing comparison. This function does all calculations in 1 CPU-based thread. 97 | virtual long filterCPU(float *outputBuffer, const float *inputBuffer, long numSamples); 98 | }; 99 | 100 | /* 101 | * FIR Filter - complex inputs, complex taps 102 | */ 103 | class FIRFilterCCC:public Filter { 104 | public: 105 | FIRFilterCCC(); 106 | FIRFilterCCC(const std::vector& newTaps); 107 | virtual ~FIRFilterCCC(); 108 | 109 | // NOTE: This routine is expecting numSamples to be an integer multiple of the number of taps 110 | virtual long filterN(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples); 111 | 112 | // OutputBuffer here should be at least numSamples/decimation in length 113 | virtual long filterNdec(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples, int decimation); 114 | 115 | virtual gr_complex filter(const gr_complex *inputBuffer); 116 | 117 | // This is for testing comparison. This function does all calculations in 1 CPU-based thread. 118 | virtual long filterCPU(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples); 119 | }; 120 | 121 | 122 | // ----------------------------------------------------------------- 123 | // ------ Multi-threaded filters ---------------------------------- 124 | // ----------------------------------------------------------------- 125 | 126 | /* 127 | * Multi-threaded base template. 128 | * Provides threading and buffers 129 | * 130 | */ 131 | template 132 | class MTBase { 133 | protected: 134 | const io_type *pInputBuffer; 135 | io_type *pOutputBuffer; 136 | 137 | // Supports up to 16 threads 138 | boost::thread *threads[16]; 139 | bool threadRunning[16]; 140 | bool threadReady; 141 | int d_nthreads; 142 | int decimation; 143 | 144 | 145 | public: 146 | MTBase(int nthreads=4); 147 | virtual ~MTBase(); 148 | 149 | int numThreads() { return d_nthreads; }; 150 | 151 | inline virtual void setDecimation(int newDecimation) { decimation = newDecimation; }; 152 | inline virtual int getDecimation() { return decimation; }; 153 | inline virtual bool decimating() { if (decimation > 1) return true; else return false; }; 154 | 155 | virtual long calcDecimationBlockSize(long numSamples); 156 | 157 | // NOTE: calcDecimationIndex assumes the index is an even multiple of a decimation block size 158 | // In other words, calcDecimationBlockSize was called to get an appropriate block size, 159 | // then blockStartIndex is an integer multiple of that result. 160 | virtual long calcDecimationIndex(long blockStartIndex); 161 | 162 | // NOTE: This method IS NOT thread-safe. Make sure to use a scoped_lock or be sure no threads are running 163 | // before changing the number of threads. 164 | virtual void setThreads(int nthreads); 165 | 166 | virtual bool anyThreadRunning(); 167 | }; 168 | 169 | // -------------------------------------------------- 170 | // Multi-threaded filter, complex data, float taps 171 | // -------------------------------------------------- 172 | class FIRFilterCCF_MT:public MTBase, public FIRFilterCCF { 173 | protected: 174 | virtual void runThread1(long startIndex,long numSamples); 175 | virtual void runThread2(long startIndex,long numSamples); 176 | virtual void runThread3(long startIndex,long numSamples); 177 | virtual void runThread4(long startIndex,long numSamples); 178 | virtual void runThread5(long startIndex,long numSamples); 179 | virtual void runThread6(long startIndex,long numSamples); 180 | virtual void runThread7(long startIndex,long numSamples); 181 | virtual void runThread8(long startIndex,long numSamples); 182 | virtual void runThread9(long startIndex,long numSamples); 183 | virtual void runThread10(long startIndex,long numSamples); 184 | virtual void runThread11(long startIndex,long numSamples); 185 | virtual void runThread12(long startIndex,long numSamples); 186 | virtual void runThread13(long startIndex,long numSamples); 187 | virtual void runThread14(long startIndex,long numSamples); 188 | virtual void runThread15(long startIndex,long numSamples); 189 | virtual void runThread16(long startIndex,long numSamples); 190 | 191 | public: 192 | FIRFilterCCF_MT(int nthreads); 193 | FIRFilterCCF_MT(const std::vector& newTaps, int nthreads); 194 | virtual ~FIRFilterCCF_MT(); 195 | 196 | // NOTE: This routine is expecting numSamples to be an integer multiple of the number of taps 197 | virtual long filterN(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples); 198 | 199 | // OutputBuffer here should be at least numSamples/decimation in length 200 | virtual long filterNdec(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples, int decimation); 201 | 202 | }; 203 | 204 | // -------------------------------------------------- 205 | // Multi-threaded filter, complex data, float taps 206 | // -------------------------------------------------- 207 | class FIRFilterFFF_MT:public MTBase, public FIRFilterFFF { 208 | protected: 209 | virtual void runThread1(long startIndex,long numSamples); 210 | virtual void runThread2(long startIndex,long numSamples); 211 | virtual void runThread3(long startIndex,long numSamples); 212 | virtual void runThread4(long startIndex,long numSamples); 213 | virtual void runThread5(long startIndex,long numSamples); 214 | virtual void runThread6(long startIndex,long numSamples); 215 | virtual void runThread7(long startIndex,long numSamples); 216 | virtual void runThread8(long startIndex,long numSamples); 217 | virtual void runThread9(long startIndex,long numSamples); 218 | virtual void runThread10(long startIndex,long numSamples); 219 | virtual void runThread11(long startIndex,long numSamples); 220 | virtual void runThread12(long startIndex,long numSamples); 221 | virtual void runThread13(long startIndex,long numSamples); 222 | virtual void runThread14(long startIndex,long numSamples); 223 | virtual void runThread15(long startIndex,long numSamples); 224 | virtual void runThread16(long startIndex,long numSamples); 225 | 226 | public: 227 | FIRFilterFFF_MT(int nthreads); 228 | FIRFilterFFF_MT(const std::vector& newTaps, int nthreads); 229 | virtual ~FIRFilterFFF_MT(); 230 | 231 | // NOTE: This routine is expecting numSamples to be an integer multiple of the number of taps 232 | virtual long filterN(float *outputBuffer, const float *inputBuffer, long numSamples); 233 | 234 | // OutputBuffer here should be at least numSamples/decimation in length 235 | virtual long filterNdec(float *outputBuffer, const float *inputBuffer, long numSamples, int decimation); 236 | }; 237 | 238 | // -------------------------------------------------- 239 | // Multi-threaded filter, complex data, complex taps 240 | // -------------------------------------------------- 241 | class FIRFilterCCC_MT:public MTBase, public FIRFilterCCC { 242 | protected: 243 | virtual void runThread1(long startIndex,long numSamples); 244 | virtual void runThread2(long startIndex,long numSamples); 245 | virtual void runThread3(long startIndex,long numSamples); 246 | virtual void runThread4(long startIndex,long numSamples); 247 | virtual void runThread5(long startIndex,long numSamples); 248 | virtual void runThread6(long startIndex,long numSamples); 249 | virtual void runThread7(long startIndex,long numSamples); 250 | virtual void runThread8(long startIndex,long numSamples); 251 | virtual void runThread9(long startIndex,long numSamples); 252 | virtual void runThread10(long startIndex,long numSamples); 253 | virtual void runThread11(long startIndex,long numSamples); 254 | virtual void runThread12(long startIndex,long numSamples); 255 | virtual void runThread13(long startIndex,long numSamples); 256 | virtual void runThread14(long startIndex,long numSamples); 257 | virtual void runThread15(long startIndex,long numSamples); 258 | virtual void runThread16(long startIndex,long numSamples); 259 | 260 | public: 261 | FIRFilterCCC_MT(int nthreads); 262 | FIRFilterCCC_MT(const std::vector& newTaps, int nthreads); 263 | virtual ~FIRFilterCCC_MT(); 264 | 265 | // NOTE: This routine is expecting numSamples to be an integer multiple of the number of taps 266 | virtual long filterN(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples); 267 | 268 | // OutputBuffer here should be at least numSamples/decimation in length 269 | virtual long filterNdec(gr_complex *outputBuffer, const gr_complex *inputBuffer, long numSamples, int decimation); 270 | }; 271 | } // end lfast 272 | } // end gr 273 | 274 | 275 | 276 | #endif /* INCLUDE_LFAST_FIR_FILTER_LFAST_H_ */ 277 | -------------------------------------------------------------------------------- /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-lfast 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 | --------------------------------------------------------------------------------