diff options
420 files changed, 25925 insertions, 5170 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a0190bdaa..3a5eb0555e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,8 @@ set(GR_PKG_CONF_DIR ${GR_CONF_DIR}/${CMAKE_PROJECT_NAME}/conf.d) set(GR_LIBEXEC_DIR libexec) set(GR_PKG_LIBEXEC_DIR ${GR_LIBEXEC_DIR}/${CMAKE_PROJECT_NAME}) set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks) +set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" CACHE PATH "System configuration directory") +set(GR_PREFSDIR ${SYSCONFDIR}/${CMAKE_PROJECT_NAME}/conf.d) ######################################################################## # Variables replaced when configuring the package config files @@ -115,6 +117,8 @@ file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}" prefix) file(TO_NATIVE_PATH "\${prefix}" exec_prefix) file(TO_NATIVE_PATH "\${exec_prefix}/${GR_LIBRARY_DIR}" libdir) file(TO_NATIVE_PATH "\${prefix}/${GR_INCLUDE_DIR}" includedir) +file(TO_NATIVE_PATH "${SYSCONFDIR}" SYSCONFDIR) +file(TO_NATIVE_PATH "${GR_PREFSDIR}" GR_PREFSDIR) ######################################################################## # Create uninstall target @@ -229,6 +233,7 @@ add_subdirectory(gnuradio-core) add_subdirectory(grc) add_subdirectory(gr-fft) +add_subdirectory(gr-filter) add_subdirectory(gr-atsc) add_subdirectory(gr-audio) add_subdirectory(gr-comedi) diff --git a/cmake/Packaging/Fedora-15.cmake b/cmake/Packaging/Fedora-15.cmake index 278d68990a..2e9e78ee11 100644 --- a/cmake/Packaging/Fedora-15.cmake +++ b/cmake/Packaging/Fedora-15.cmake @@ -1,6 +1,6 @@ SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "boost-python" "glibc") SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") -SET(PACKAGE_DEPENDS_CORE_RUNTIME "fftw-libs" "gsl") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "fftw-libs") SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "qt" "qwt") SET(PACKAGE_DEPENDS_QTGUI_PYTHON "PyQt4" "PyQwt") SET(PACKAGE_DEPENDS_GRC "python" "numpy" "gtk2" "python-lxml" "python-cheetah") @@ -8,3 +8,5 @@ SET(PACKAGE_DEPENDS_WXGUI "wxGTK" "python" "numpy") SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "SDL") SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "pulseaudio" "alsa-lib" "jack-audio-connection-kit") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "gsl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "numpy") diff --git a/cmake/Packaging/Fedora-16.cmake b/cmake/Packaging/Fedora-16.cmake index 278d68990a..2e9e78ee11 100644 --- a/cmake/Packaging/Fedora-16.cmake +++ b/cmake/Packaging/Fedora-16.cmake @@ -1,6 +1,6 @@ SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "boost-python" "glibc") SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") -SET(PACKAGE_DEPENDS_CORE_RUNTIME "fftw-libs" "gsl") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "fftw-libs") SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "qt" "qwt") SET(PACKAGE_DEPENDS_QTGUI_PYTHON "PyQt4" "PyQwt") SET(PACKAGE_DEPENDS_GRC "python" "numpy" "gtk2" "python-lxml" "python-cheetah") @@ -8,3 +8,5 @@ SET(PACKAGE_DEPENDS_WXGUI "wxGTK" "python" "numpy") SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "SDL") SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "pulseaudio" "alsa-lib" "jack-audio-connection-kit") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "gsl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "numpy") diff --git a/cmake/Packaging/Fedora-17.cmake b/cmake/Packaging/Fedora-17.cmake new file mode 100644 index 0000000000..2e9e78ee11 --- /dev/null +++ b/cmake/Packaging/Fedora-17.cmake @@ -0,0 +1,12 @@ +SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "boost-python" "glibc") +SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "fftw-libs") +SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "qt" "qwt") +SET(PACKAGE_DEPENDS_QTGUI_PYTHON "PyQt4" "PyQwt") +SET(PACKAGE_DEPENDS_GRC "python" "numpy" "gtk2" "python-lxml" "python-cheetah") +SET(PACKAGE_DEPENDS_WXGUI "wxGTK" "python" "numpy") +SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "SDL") +SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") +SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "pulseaudio" "alsa-lib" "jack-audio-connection-kit") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "gsl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "numpy") diff --git a/cmake/Packaging/Ubuntu-10.04.cmake b/cmake/Packaging/Ubuntu-10.04.cmake index a7a60f6b80..3320073c6b 100644 --- a/cmake/Packaging/Ubuntu-10.04.cmake +++ b/cmake/Packaging/Ubuntu-10.04.cmake @@ -1,6 +1,6 @@ SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "libboost-all-dev" "libc6") SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") -SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3" "libgsl0ldbl") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3") SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "libqtcore4" "libqwt5-qt4") SET(PACKAGE_DEPENDS_QTGUI_PYTHON "python-qt4" "python-qwt5-qt4") SET(PACKAGE_DEPENDS_GRC "python" "python-numpy" "python-gtk2" "python-lxml" "python-cheetah") @@ -8,3 +8,5 @@ SET(PACKAGE_DEPENDS_WXGUI "python-wxgtk2.8" "python" "python-numpy") SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "libsdl1.2debian") SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "libpulse0" "alsa-base" "libjack0") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "libgsl0ldbl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "python-numpy") diff --git a/cmake/Packaging/Ubuntu-10.10.cmake b/cmake/Packaging/Ubuntu-10.10.cmake index a7a60f6b80..3320073c6b 100644 --- a/cmake/Packaging/Ubuntu-10.10.cmake +++ b/cmake/Packaging/Ubuntu-10.10.cmake @@ -1,6 +1,6 @@ SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "libboost-all-dev" "libc6") SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") -SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3" "libgsl0ldbl") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3") SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "libqtcore4" "libqwt5-qt4") SET(PACKAGE_DEPENDS_QTGUI_PYTHON "python-qt4" "python-qwt5-qt4") SET(PACKAGE_DEPENDS_GRC "python" "python-numpy" "python-gtk2" "python-lxml" "python-cheetah") @@ -8,3 +8,5 @@ SET(PACKAGE_DEPENDS_WXGUI "python-wxgtk2.8" "python" "python-numpy") SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "libsdl1.2debian") SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "libpulse0" "alsa-base" "libjack0") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "libgsl0ldbl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "python-numpy") diff --git a/cmake/Packaging/Ubuntu-11.04.cmake b/cmake/Packaging/Ubuntu-11.04.cmake index 71882b2e1f..c166bcf427 100644 --- a/cmake/Packaging/Ubuntu-11.04.cmake +++ b/cmake/Packaging/Ubuntu-11.04.cmake @@ -1,7 +1,7 @@ #set the debian package dependencies (parsed by our deb component maker) SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "libboost-all-dev" "libc6") SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python") -SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3" "libgsl0ldbl") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3") SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "libqtcore4" "libqwt5-qt4") SET(PACKAGE_DEPENDS_QTGUI_PYTHON "python-qt4" "python-qwt5-qt4") SET(PACKAGE_DEPENDS_GRC "python" "python-numpy" "python-gtk2" "python-lxml" "python-cheetah") @@ -9,3 +9,5 @@ SET(PACKAGE_DEPENDS_WXGUI "python-wxgtk2.8") SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "libsdl1.2debian") SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "libpulse0" "alsa-base" "libjack0") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "libgsl0ldbl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "python-numpy") diff --git a/cmake/Packaging/Ubuntu-11.10.cmake b/cmake/Packaging/Ubuntu-11.10.cmake index dcb7b31783..702ce574f3 100644 --- a/cmake/Packaging/Ubuntu-11.10.cmake +++ b/cmake/Packaging/Ubuntu-11.10.cmake @@ -1,6 +1,6 @@ SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "libboost-all-dev" "libc6") SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python" "python-numpy") -SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3" "libgsl0ldbl") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3") SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "libqtcore4" "libqwt6") SET(PACKAGE_DEPENDS_QTGUI_PYTHON "python-qt4" "python-qwt5-qt4") SET(PACKAGE_DEPENDS_GRC "python" "python-numpy" "python-gtk2" "python-lxml" "python-cheetah") @@ -8,3 +8,5 @@ SET(PACKAGE_DEPENDS_WXGUI "python-wxgtk2.8") SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "libsdl1.2debian") SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "libpulse0" "alsa-base" "libjack0") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "libgsl0ldbl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "python-numpy") diff --git a/cmake/Packaging/Ubuntu-12.04.cmake b/cmake/Packaging/Ubuntu-12.04.cmake new file mode 100644 index 0000000000..702ce574f3 --- /dev/null +++ b/cmake/Packaging/Ubuntu-12.04.cmake @@ -0,0 +1,12 @@ +SET(PACKAGE_DEPENDS_GRUEL_RUNTIME "libboost-all-dev" "libc6") +SET(PACKAGE_DEPENDS_GRUEL_PYTHON "python" "python-numpy") +SET(PACKAGE_DEPENDS_CORE_RUNTIME "libfftw3-3") +SET(PACKAGE_DEPENDS_QTGUI_RUNTIME "libqtcore4" "libqwt6") +SET(PACKAGE_DEPENDS_QTGUI_PYTHON "python-qt4" "python-qwt5-qt4") +SET(PACKAGE_DEPENDS_GRC "python" "python-numpy" "python-gtk2" "python-lxml" "python-cheetah") +SET(PACKAGE_DEPENDS_WXGUI "python-wxgtk2.8") +SET(PACKAGE_DEPENDS_VIDEO_SDL_RUNTIME "libsdl1.2debian") +SET(PACKAGE_DEPENDS_UHD_RUNTIME "uhd") +SET(PACKAGE_DEPENDS_AUDIO_RUNTIME "libpulse0" "alsa-base" "libjack0") +SET(PACKAGE_DEPENDS_WAVELET_RUNTIME "libgsl0ldbl") +SET(PACKAGE_DEPENDS_WAVELET_PYTHON "python" "python-numpy") diff --git a/docs/doxygen/doxyxml/doxyindex.py b/docs/doxygen/doxyxml/doxyindex.py index 84bc7b88c3..304109a8e5 100644 --- a/docs/doxygen/doxyxml/doxyindex.py +++ b/docs/doxygen/doxyxml/doxyindex.py @@ -80,12 +80,28 @@ class DoxyCompMem(Base): self._data['brief_description'] = bd self._data['detailed_description'] = dd + def set_parameters(self, data): + vs = [ddc.value for ddc in data.detaileddescription.content_] + pls = [] + for v in vs: + if hasattr(v, 'parameterlist'): + pls += v.parameterlist + pis = [] + for pl in pls: + pis += pl.parameteritem + dpis = [] + for pi in pis: + dpi = DoxyParameterItem(pi) + dpi._parse() + dpis.append(dpi) + self._data['params'] = dpis + + class DoxyCompound(DoxyCompMem): pass class DoxyMember(DoxyCompMem): pass - class DoxyFunction(DoxyMember): @@ -98,10 +114,13 @@ class DoxyFunction(DoxyMember): return super(DoxyFunction, self)._parse() self.set_descriptions(self._parse_data) - self._data['params'] = [] - prms = self._parse_data.param - for prm in prms: - self._data['params'].append(DoxyParam(prm)) + self.set_parameters(self._parse_data) + if not self._data['params']: + # If the params weren't set by a comment then just grab the names. + self._data['params'] = [] + prms = self._parse_data.param + for prm in prms: + self._data['params'].append(DoxyParam(prm)) brief_description = property(lambda self: self.data()['brief_description']) detailed_description = property(lambda self: self.data()['detailed_description']) @@ -121,9 +140,18 @@ class DoxyParam(DoxyMember): self.set_descriptions(self._parse_data) self._data['declname'] = self._parse_data.declname + @property + def description(self): + descriptions = [] + if self.brief_description: + descriptions.append(self.brief_description) + if self.detailed_description: + descriptions.append(self.detailed_description) + return '\n\n'.join(descriptions) + brief_description = property(lambda self: self.data()['brief_description']) detailed_description = property(lambda self: self.data()['detailed_description']) - declname = property(lambda self: self.data()['declname']) + name = property(lambda self: self.data()['declname']) class DoxyParameterItem(DoxyMember): """A different representation of a parameter in Doxygen.""" @@ -165,22 +193,6 @@ class DoxyClass(DoxyCompound): # We just ignore this for now. self.process_memberdefs() - def set_parameters(self, data): - vs = [ddc.value for ddc in data.detaileddescription.content_] - pls = [] - for v in vs: - if hasattr(v, 'parameterlist'): - pls += v.parameterlist - pis = [] - for pl in pls: - pis += pl.parameteritem - dpis = [] - for pi in pis: - dpi = DoxyParameterItem(pi) - dpi._parse() - dpis.append(dpi) - self._data['params'] = dpis - brief_description = property(lambda self: self.data()['brief_description']) detailed_description = property(lambda self: self.data()['detailed_description']) params = property(lambda self: self.data()['params']) diff --git a/docs/doxygen/other/volk_guide.dox b/docs/doxygen/other/volk_guide.dox index 24882ed1a6..0e444ebbaf 100644 --- a/docs/doxygen/other/volk_guide.dox +++ b/docs/doxygen/other/volk_guide.dox @@ -63,7 +63,7 @@ calls with: \code const int alignment_multiple = volk_get_alignment() / output_item_size; - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); \endcode The Volk function 'volk_get_alignment' provides the alignment of the diff --git a/docs/doxygen/swig_doc.py b/docs/doxygen/swig_doc.py index 414748bbae..9277470984 100644 --- a/docs/doxygen/swig_doc.py +++ b/docs/doxygen/swig_doc.py @@ -29,7 +29,8 @@ python docstrings. import sys, time -from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base +from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile +from doxyxml import DoxyOther, base def py_name(name): bits = name.split('_') @@ -54,8 +55,27 @@ class Block(object): return False friendname = make_name(item.name()) is_a_block = item.has_member(friendname, DoxyFriend) + # But now sometimes the make function isn't a friend so check again. + if not is_a_block: + is_a_block = di.has_member(friendname, DoxyFunction) return is_a_block +class Block2(object): + """ + Checks if doxyxml produced objects correspond to a new style + gnuradio block. + """ + + @classmethod + def includes(cls, item): + if not isinstance(item, DoxyClass): + return False + # Check for a parsing error. + if item.error(): + return False + is_a_block2 = item.has_member('make', DoxyFunction) and item.has_member('sptr', DoxyOther) + return is_a_block2 + def utoascii(text): """ @@ -141,15 +161,18 @@ def make_func_entry(func, name=None, description=None, params=None): return make_entry(func, name=name, description=description, params=params) -def make_class_entry(klass, description=None): +def make_class_entry(klass, description=None, ignored_methods=[], params=None): """ Create a class docstring for a swig interface file. """ + if params is None: + params = klass.params output = [] - output.append(make_entry(klass, description=description, params=klass.params)) + output.append(make_entry(klass, description=description, params=params)) for func in klass.in_category(DoxyFunction): - name = klass.name() + '::' + func.name() - output.append(make_func_entry(func, name=name)) + if func.name() not in ignored_methods: + name = klass.name() + '::' + func.name() + output.append(make_func_entry(func, name=name)) return "\n\n".join(output) @@ -183,11 +206,32 @@ def make_block_entry(di, block): # the make function. output = [] output.append(make_class_entry(block, description=super_description)) - creator = block.get_member(block.name(), DoxyFunction) output.append(make_func_entry(make_func, description=super_description, params=block.params)) return "\n\n".join(output) +def make_block2_entry(di, block): + """ + Create class and function docstrings of a new style gnuradio block for a + swig interface file. + """ + descriptions = [] + # For new style blocks all the relevant documentation should be + # associated with the 'make' method. + make_func = block.get_member('make', DoxyFunction) + description = combine_descriptions(make_func) + # Associate the combined description with the class and + # the make function. + output = [] + #output.append(make_class_entry( + # block, description=description, + # ignored_methods=['make'], params=make_func.params)) + makename = block.name() + '::make' + output.append(make_func_entry( + make_func, name=makename, description=description, + params=make_func.params)) + return "\n\n".join(output) + def wait_if_necessary(tries, swigdocfilename, item=None): if item is not None: extra = ', item {0}'.format(item.name()) @@ -223,6 +267,7 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None, tries=0): while(1): try: blocks = di.in_category(Block) + blocks2 = di.in_category(Block2) except: tries, try_again = wait_if_necessary(tries, swigdocfilename) if not try_again: @@ -246,10 +291,28 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None, tries=0): raise else: break + for block in blocks2: + while(1): + try: + make_func = block.get_member('make', DoxyFunction) + make_func_name = block.name() +'::make' + # Don't want to risk writing to output twice. + if make_func_name not in make_funcs: + make_funcs.add(make_func_name) + output.append(make_block2_entry(di, block)) + except block.ParsingError: + sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) + except: + tries, try_again = wait_if_necessary(tries, swigdocfilename, block) + if not try_again: + raise + else: + break # Create docstrings for functions # Don't include the make functions since they have already been dealt with. - funcs = [f for f in di.in_category(DoxyFunction) if f.name() not in make_funcs] + funcs = [f for f in di.in_category(DoxyFunction) + if f.name() not in make_funcs and not f.name().startswith('std::')] for f in funcs: try: output.append(make_func_entry(f)) @@ -258,7 +321,9 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None, tries=0): # Create docstrings for classes block_names = [block.name() for block in blocks] - klasses = [k for k in di.in_category(DoxyClass) if k.name() not in block_names] + block_names += [block.name() for block in blocks2] + klasses = [k for k in di.in_category(DoxyClass) + if k.name() not in block_names and not k.name().startswith('std::')] for k in klasses: try: output.append(make_class_entry(k)) diff --git a/docs/sphinx/README b/docs/sphinx/README index c3ac382648..0ae3a43f84 100644 --- a/docs/sphinx/README +++ b/docs/sphinx/README @@ -48,7 +48,7 @@ examples. under the "Slicing and Dicing Streams" subheading. Edit file gnuradio/docs/sphinx/source/gr/slicedice_blk.rst and add the line - >.. autoblock:: gnuradio.gr.myslicer + >.. autooldblock:: gnuradio.gr.myslicer 2) Adding a new python hierarchical block gnuradio.digital.mymod Edit file gnruadio/docs/sphinx/source/digital/index.rst and add the @@ -63,7 +63,10 @@ examples. a python hierarchical signal processing block so that it can format it appropriately. -The process for documenting objects that are not signal processing blocks is -similar but rather than using the 'autoblock' and 'autopyblock' directives -the standard sphinx directives such as 'autofunction' and 'autoclass' can -be used.
\ No newline at end of file +The process for documenting objects that are not signal processing +blocks is similar but rather than using the 'autooldblock', and +'autopyblock' directives the standard sphinx directives such as +'autofunction' and 'autoclass' can be used. + +Finally for signal processing blocks using the 3.7 style the directive +'autoblock' rather than 'autooldblock' can be used.
\ No newline at end of file diff --git a/docs/sphinx/gnuradio_sphinx.py b/docs/sphinx/gnuradio_sphinx.py index 6f35a6fce9..e8ca867f8c 100644 --- a/docs/sphinx/gnuradio_sphinx.py +++ b/docs/sphinx/gnuradio_sphinx.py @@ -15,6 +15,7 @@ def setup(sp): sp.connect('autodoc-process-signature', fix_signature) sp.connect('autodoc-process-docstring', remove_lines) # Add node to autodocument signal-processing blocks. + sp.add_autodocumenter(OldBlockDocumenter) sp.add_autodocumenter(BlockDocumenter) sp.add_autodocumenter(PyBlockDocumenter) @@ -105,9 +106,10 @@ common_block_members =[ 'thisown', 'to_basic_block', 'unique_id', + 'make', ] -class BlockDocumenter(FunctionDocumenter): +class OldBlockDocumenter(FunctionDocumenter): """ Specialized Documenter subclass for gnuradio blocks. @@ -115,13 +117,13 @@ class BlockDocumenter(FunctionDocumenter): with the wrapped sptr (e.g. gr.gr_head_sptr) to keep the documentation tidier. """ - objtype = 'block' + objtype = 'oldblock' directivetype = 'function' # Don't want to use this for generic functions for give low priority. priority = -10 def __init__(self, *args, **kwargs): - super(BlockDocumenter, self).__init__(*args, **kwargs) + super(OldBlockDocumenter, self).__init__(*args, **kwargs) # Get class name bits = self.name.split('.') if len(bits) != 3 or bits[0] != 'gnuradio': @@ -129,6 +131,36 @@ class BlockDocumenter(FunctionDocumenter): sptr_name = 'gnuradio.{0}.{0}_{1}_sptr'.format(bits[1], bits[2]) # Create a Class Documenter to create documentation for the classes members. self.classdoccer = ClassDocumenter(self.directive, sptr_name, indent=self.content_indent) + self.classdoccer.doc_as_attr = False + self.classdoccer.real_modname = self.classdoccer.get_real_modname() + self.classdoccer.options.members = ALL + self.classdoccer.options.exclude_members = common_block_members + self.classdoccer.parse_name() + self.classdoccer.import_object() + + def document_members(self, *args, **kwargs): + return self.classdoccer.document_members(*args, **kwargs) + +class BlockDocumenter(FunctionDocumenter): + """ + Specialized Documenter subclass for new style gnuradio blocks. + + It merges together the documentation for the generator function (e.g. wavelet.squash_ff) + with the wrapped sptr (e.g. wavelet.squash_ff_sptr) to keep the documentation + tidier. + """ + objtype = 'block' + directivetype = 'function' + # Don't want to use this for generic functions for give low priority. + priority = -10 + + def __init__(self, *args, **kwargs): + super(BlockDocumenter, self).__init__(*args, **kwargs) + # Get class name + sptr_name = self.name + '_sptr' + # Create a Class Documenter to create documentation for the classes members. + self.classdoccer = ClassDocumenter(self.directive, sptr_name, indent=self.content_indent) + self.classdoccer.doc_as_attr = False self.classdoccer.real_modname = self.classdoccer.get_real_modname() self.classdoccer.options.members = ALL self.classdoccer.options.exclude_members = common_block_members diff --git a/docs/sphinx/source/atsc/blks.rst b/docs/sphinx/source/atsc/blks.rst index ce26f095b1..6f51a22876 100644 --- a/docs/sphinx/source/atsc/blks.rst +++ b/docs/sphinx/source/atsc/blks.rst @@ -1,20 +1,20 @@ gnuradio.atsc: Signal Processing Blocks ======================================= -.. autoblock:: gnuradio.atsc.bit_timing_loop -.. autoblock:: gnuradio.atsc.deinterleaver -.. autoblock:: gnuradio.atsc.depad -.. autoblock:: gnuradio.atsc.derandomizer -.. autoblock:: gnuradio.atsc.ds_to_softds -.. autoblock:: gnuradio.atsc.equalizer -.. autoblock:: gnuradio.atsc.field_sync_demux -.. autoblock:: gnuradio.atsc.field_sync_mux -.. autoblock:: gnuradio.atsc.fpll -.. autoblock:: gnuradio.atsc.fs_checker -.. autoblock:: gnuradio.atsc.interleaver -.. autoblock:: gnuradio.atsc.pad -.. autoblock:: gnuradio.atsc.randomizer -.. autoblock:: gnuradio.atsc.rs_decoder -.. autoblock:: gnuradio.atsc.rs_encoder -.. autoblock:: gnuradio.atsc.trellis_encoder -.. autoblock:: gnuradio.atsc.viterbi_decoder +.. autooldblock:: gnuradio.atsc.bit_timing_loop +.. autooldblock:: gnuradio.atsc.deinterleaver +.. autooldblock:: gnuradio.atsc.depad +.. autooldblock:: gnuradio.atsc.derandomizer +.. autooldblock:: gnuradio.atsc.ds_to_softds +.. autooldblock:: gnuradio.atsc.equalizer +.. autooldblock:: gnuradio.atsc.field_sync_demux +.. autooldblock:: gnuradio.atsc.field_sync_mux +.. autooldblock:: gnuradio.atsc.fpll +.. autooldblock:: gnuradio.atsc.fs_checker +.. autooldblock:: gnuradio.atsc.interleaver +.. autooldblock:: gnuradio.atsc.pad +.. autooldblock:: gnuradio.atsc.randomizer +.. autooldblock:: gnuradio.atsc.rs_decoder +.. autooldblock:: gnuradio.atsc.rs_encoder +.. autooldblock:: gnuradio.atsc.trellis_encoder +.. autooldblock:: gnuradio.atsc.viterbi_decoder diff --git a/docs/sphinx/source/audio/index.rst b/docs/sphinx/source/audio/index.rst index 31d53567b8..d0bc4f3c08 100644 --- a/docs/sphinx/source/audio/index.rst +++ b/docs/sphinx/source/audio/index.rst @@ -3,5 +3,5 @@ gnuradio.audio .. automodule:: gnuradio.audio -.. autoblock:: gnuradio.audio.source -.. autoblock:: gnuradio.audio.sink +.. autooldblock:: gnuradio.audio.source +.. autooldblock:: gnuradio.audio.sink diff --git a/docs/sphinx/source/digital/blocks.rst b/docs/sphinx/source/digital/blocks.rst index 2ac228d4ea..68ec8dad1c 100644 --- a/docs/sphinx/source/digital/blocks.rst +++ b/docs/sphinx/source/digital/blocks.rst @@ -1,22 +1,22 @@ gnuradio.digital: Signal Processing Blocks ========================================== -.. autoblock:: gnuradio.digital.fll_band_edge_cc -.. autoblock:: gnuradio.digital.kurtotic_equalizer_cc -.. autoblock:: gnuradio.digital.lms_dd_equalizer_cc -.. autoblock:: gnuradio.digital.mpsk_receiver_cc -.. autoblock:: gnuradio.digital.mpsk_snr_est_cc -.. autoblock:: gnuradio.digital.clock_recovery_mm_cc -.. autoblock:: gnuradio.digital.clock_recovery_mm_ff -.. autoblock:: gnuradio.digital.constellation_decoder_cb -.. autoblock:: gnuradio.digital.constellation_receiver_cb -.. autoblock:: gnuradio.digital.correlate_access_code_bb -.. autoblock:: gnuradio.digital.costas_loop_cc -.. autoblock:: gnuradio.digital.cma_equalizer_cc -.. autoblock:: gnuradio.digital.binary_slicer_fb -.. autoblock:: gnuradio.digital.gmskmod_bc -.. autoblock:: gnuradio.digital.probe_mpsk_snr_est_c -.. autoblock:: gnuradio.digital.cpmmod_bc +.. autooldblock:: gnuradio.digital.fll_band_edge_cc +.. autooldblock:: gnuradio.digital.kurtotic_equalizer_cc +.. autooldblock:: gnuradio.digital.lms_dd_equalizer_cc +.. autooldblock:: gnuradio.digital.mpsk_receiver_cc +.. autooldblock:: gnuradio.digital.mpsk_snr_est_cc +.. autooldblock:: gnuradio.digital.clock_recovery_mm_cc +.. autooldblock:: gnuradio.digital.clock_recovery_mm_ff +.. autooldblock:: gnuradio.digital.constellation_decoder_cb +.. autooldblock:: gnuradio.digital.constellation_receiver_cb +.. autooldblock:: gnuradio.digital.correlate_access_code_bb +.. autooldblock:: gnuradio.digital.costas_loop_cc +.. autooldblock:: gnuradio.digital.cma_equalizer_cc +.. autooldblock:: gnuradio.digital.binary_slicer_fb +.. autooldblock:: gnuradio.digital.gmskmod_bc +.. autooldblock:: gnuradio.digital.probe_mpsk_snr_est_c +.. autooldblock:: gnuradio.digital.cpmmod_bc .. autopyblock:: gnuradio.digital.generic_demod .. autopyblock:: gnuradio.digital.generic_mod .. autopyblock:: gnuradio.digital.bpsk.dbpsk_demod diff --git a/docs/sphinx/source/fft.rst b/docs/sphinx/source/fft.rst new file mode 100644 index 0000000000..79a0a4ed2a --- /dev/null +++ b/docs/sphinx/source/fft.rst @@ -0,0 +1,8 @@ +gnuradio.fft +============ + +.. automodule:: gnuradio.fft + +.. autoblock:: gnuradio.fft.fft_vcc +.. autoblock:: gnuradio.fft.fft_vfc +.. autoblock:: gnuradio.fft.goertzel_fc diff --git a/docs/sphinx/source/gr/coding_blk.rst b/docs/sphinx/source/gr/coding_blk.rst index 87196a5aeb..e50b990bcd 100644 --- a/docs/sphinx/source/gr/coding_blk.rst +++ b/docs/sphinx/source/gr/coding_blk.rst @@ -1,11 +1,11 @@ gnuradio.gr: Information Coding and Decoding ============================================ -.. autoblock:: gnuradio.gr.additive_scrambler_bb -.. autoblock:: gnuradio.gr.descrambler_bb -.. autoblock:: gnuradio.gr.diff_decoder_bb -.. autoblock:: gnuradio.gr.diff_encoder_bb -.. autoblock:: gnuradio.gr.fake_channel_encoder_pp -.. autoblock:: gnuradio.gr.fake_channel_decoder_pp -.. autoblock:: gnuradio.gr.map_bb -.. autoblock:: gnuradio.gr.scrambler_bb +.. autooldblock:: gnuradio.gr.additive_scrambler_bb +.. autooldblock:: gnuradio.gr.descrambler_bb +.. autooldblock:: gnuradio.gr.diff_decoder_bb +.. autooldblock:: gnuradio.gr.diff_encoder_bb +.. autooldblock:: gnuradio.gr.fake_channel_encoder_pp +.. autooldblock:: gnuradio.gr.fake_channel_decoder_pp +.. autooldblock:: gnuradio.gr.map_bb +.. autooldblock:: gnuradio.gr.scrambler_bb diff --git a/docs/sphinx/source/gr/converter_blk.rst b/docs/sphinx/source/gr/converter_blk.rst index b0ddd1d8a9..790109a94f 100644 --- a/docs/sphinx/source/gr/converter_blk.rst +++ b/docs/sphinx/source/gr/converter_blk.rst @@ -1,32 +1,32 @@ gnuradio.gr: Type Conversions ============================= -.. autoblock:: gnuradio.gr.bytes_to_syms -.. autoblock:: gnuradio.gr.char_to_float -.. autoblock:: gnuradio.gr.complex_to_interleaved_short -.. autoblock:: gnuradio.gr.complex_to_float -.. autoblock:: gnuradio.gr.complex_to_real -.. autoblock:: gnuradio.gr.complex_to_imag -.. autoblock:: gnuradio.gr.complex_to_mag -.. autoblock:: gnuradio.gr.complex_to_mag_squared -.. autoblock:: gnuradio.gr.complex_to_arg -.. autoblock:: gnuradio.gr.float_to_char -.. autoblock:: gnuradio.gr.float_to_complex -.. autoblock:: gnuradio.gr.float_to_short -.. autoblock:: gnuradio.gr.float_to_uchar -.. autoblock:: gnuradio.gr.interleaved_short_to_complex -.. autoblock:: gnuradio.gr.short_to_float -.. autoblock:: gnuradio.gr.uchar_to_float -.. autoblock:: gnuradio.gr.unpack_k_bits_bb -.. autoblock:: gnuradio.gr.chunks_to_symbols_bc -.. autoblock:: gnuradio.gr.chunks_to_symbols_bf -.. autoblock:: gnuradio.gr.chunks_to_symbols_ic -.. autoblock:: gnuradio.gr.chunks_to_symbols_if -.. autoblock:: gnuradio.gr.chunks_to_symbols_sc -.. autoblock:: gnuradio.gr.chunks_to_symbols_sf -.. autoblock:: gnuradio.gr.packed_to_unpacked_bb -.. autoblock:: gnuradio.gr.packed_to_unpacked_ii -.. autoblock:: gnuradio.gr.packed_to_unpacked_ss -.. autoblock:: gnuradio.gr.unpacked_to_packed_bb -.. autoblock:: gnuradio.gr.unpacked_to_packed_ii -.. autoblock:: gnuradio.gr.unpacked_to_packed_ss +.. autooldblock:: gnuradio.gr.bytes_to_syms +.. autooldblock:: gnuradio.gr.char_to_float +.. autooldblock:: gnuradio.gr.complex_to_interleaved_short +.. autooldblock:: gnuradio.gr.complex_to_float +.. autooldblock:: gnuradio.gr.complex_to_real +.. autooldblock:: gnuradio.gr.complex_to_imag +.. autooldblock:: gnuradio.gr.complex_to_mag +.. autooldblock:: gnuradio.gr.complex_to_mag_squared +.. autooldblock:: gnuradio.gr.complex_to_arg +.. autooldblock:: gnuradio.gr.float_to_char +.. autooldblock:: gnuradio.gr.float_to_complex +.. autooldblock:: gnuradio.gr.float_to_short +.. autooldblock:: gnuradio.gr.float_to_uchar +.. autooldblock:: gnuradio.gr.interleaved_short_to_complex +.. autooldblock:: gnuradio.gr.short_to_float +.. autooldblock:: gnuradio.gr.uchar_to_float +.. autooldblock:: gnuradio.gr.unpack_k_bits_bb +.. autooldblock:: gnuradio.gr.chunks_to_symbols_bc +.. autooldblock:: gnuradio.gr.chunks_to_symbols_bf +.. autooldblock:: gnuradio.gr.chunks_to_symbols_ic +.. autooldblock:: gnuradio.gr.chunks_to_symbols_if +.. autooldblock:: gnuradio.gr.chunks_to_symbols_sc +.. autooldblock:: gnuradio.gr.chunks_to_symbols_sf +.. autooldblock:: gnuradio.gr.packed_to_unpacked_bb +.. autooldblock:: gnuradio.gr.packed_to_unpacked_ii +.. autooldblock:: gnuradio.gr.packed_to_unpacked_ss +.. autooldblock:: gnuradio.gr.unpacked_to_packed_bb +.. autooldblock:: gnuradio.gr.unpacked_to_packed_ii +.. autooldblock:: gnuradio.gr.unpacked_to_packed_ss diff --git a/docs/sphinx/source/gr/demodulation_blk.rst b/docs/sphinx/source/gr/demodulation_blk.rst index e5a9354340..4f800b642b 100644 --- a/docs/sphinx/source/gr/demodulation_blk.rst +++ b/docs/sphinx/source/gr/demodulation_blk.rst @@ -1,4 +1,4 @@ gnuradio.gr: Demodulation ========================= -.. autoblock:: gnuradio.gr.quadrature_demod_cf +.. autooldblock:: gnuradio.gr.quadrature_demod_cf diff --git a/docs/sphinx/source/gr/dft_blk.rst b/docs/sphinx/source/gr/dft_blk.rst index a93119969b..4ac1d2e621 100644 --- a/docs/sphinx/source/gr/dft_blk.rst +++ b/docs/sphinx/source/gr/dft_blk.rst @@ -1,6 +1,6 @@ gnuradio.gr: Fourier Transform ============================== -.. autoblock:: gnuradio.gr.goertzel_fc -.. autoblock:: gnuradio.gr.fft_vcc -.. autoblock:: gnuradio.gr.fft_vfc +.. autooldblock:: gnuradio.gr.goertzel_fc +.. autooldblock:: gnuradio.gr.fft_vcc +.. autooldblock:: gnuradio.gr.fft_vfc diff --git a/docs/sphinx/source/gr/filter_blk.rst b/docs/sphinx/source/gr/filter_blk.rst index 767ee4b741..a73ddda2a8 100644 --- a/docs/sphinx/source/gr/filter_blk.rst +++ b/docs/sphinx/source/gr/filter_blk.rst @@ -1,46 +1,46 @@ gnuradio.gr: Filters ==================== -.. autoblock:: gnuradio.gr.fft_filter_ccc -.. autoblock:: gnuradio.gr.fft_filter_fff -.. autoblock:: gnuradio.gr.filter_delay_fc -.. autoblock:: gnuradio.gr.fir_filter_ccc -.. autoblock:: gnuradio.gr.fir_filter_ccf -.. autoblock:: gnuradio.gr.fir_filter_fcc -.. autoblock:: gnuradio.gr.fir_filter_fff -.. autoblock:: gnuradio.gr.fir_filter_fsf -.. autoblock:: gnuradio.gr.fir_filter_scc -.. autoblock:: gnuradio.gr.fractional_interpolator_cc -.. autoblock:: gnuradio.gr.fractional_interpolator_ff -.. autoblock:: gnuradio.gr.freq_xlating_fir_filter_ccc -.. autoblock:: gnuradio.gr.freq_xlating_fir_filter_ccf -.. autoblock:: gnuradio.gr.freq_xlating_fir_filter_fcc -.. autoblock:: gnuradio.gr.freq_xlating_fir_filter_fcf -.. autoblock:: gnuradio.gr.freq_xlating_fir_filter_scc -.. autoblock:: gnuradio.gr.freq_xlating_fir_filter_scf -.. autoblock:: gnuradio.gr.hilbert_fc -.. autoblock:: gnuradio.gr.iir_filter_ffd -.. autoblock:: gnuradio.gr.interp_fir_filter_ccc -.. autoblock:: gnuradio.gr.interp_fir_filter_ccf -.. autoblock:: gnuradio.gr.interp_fir_filter_fcc -.. autoblock:: gnuradio.gr.interp_fir_filter_fff -.. autoblock:: gnuradio.gr.interp_fir_filter_fsf -.. autoblock:: gnuradio.gr.interp_fir_filter_scc -.. autoblock:: gnuradio.gr.rational_resampler_base_ccc -.. autoblock:: gnuradio.gr.rational_resampler_base_ccf -.. autoblock:: gnuradio.gr.rational_resampler_base_fcc -.. autoblock:: gnuradio.gr.rational_resampler_base_fff -.. autoblock:: gnuradio.gr.rational_resampler_base_fsf -.. autoblock:: gnuradio.gr.rational_resampler_base_scc -.. autoblock:: gnuradio.gr.single_pole_iir_filter_cc -.. autoblock:: gnuradio.gr.single_pole_iir_filter_ff -.. autoblock:: gnuradio.gr.moving_average_cc -.. autoblock:: gnuradio.gr.moving_average_ff -.. autoblock:: gnuradio.gr.moving_average_ii -.. autoblock:: gnuradio.gr.moving_average_ss -.. autoblock:: gnuradio.gr.pfb_arb_resampler_ccf -.. autoblock:: gnuradio.gr.pfb_channelizer_ccf -.. autoblock:: gnuradio.gr.pfb_clock_sync_ccf -.. autoblock:: gnuradio.gr.pfb_clock_sync_fff -.. autoblock:: gnuradio.gr.pfb_decimator_ccf -.. autoblock:: gnuradio.gr.pfb_interpolator_ccf +.. autooldblock:: gnuradio.gr.fft_filter_ccc +.. autooldblock:: gnuradio.gr.fft_filter_fff +.. autooldblock:: gnuradio.gr.filter_delay_fc +.. autooldblock:: gnuradio.gr.fir_filter_ccc +.. autooldblock:: gnuradio.gr.fir_filter_ccf +.. autooldblock:: gnuradio.gr.fir_filter_fcc +.. autooldblock:: gnuradio.gr.fir_filter_fff +.. autooldblock:: gnuradio.gr.fir_filter_fsf +.. autooldblock:: gnuradio.gr.fir_filter_scc +.. autooldblock:: gnuradio.gr.fractional_interpolator_cc +.. autooldblock:: gnuradio.gr.fractional_interpolator_ff +.. autooldblock:: gnuradio.gr.freq_xlating_fir_filter_ccc +.. autooldblock:: gnuradio.gr.freq_xlating_fir_filter_ccf +.. autooldblock:: gnuradio.gr.freq_xlating_fir_filter_fcc +.. autooldblock:: gnuradio.gr.freq_xlating_fir_filter_fcf +.. autooldblock:: gnuradio.gr.freq_xlating_fir_filter_scc +.. autooldblock:: gnuradio.gr.freq_xlating_fir_filter_scf +.. autooldblock:: gnuradio.gr.hilbert_fc +.. autooldblock:: gnuradio.gr.iir_filter_ffd +.. autooldblock:: gnuradio.gr.interp_fir_filter_ccc +.. autooldblock:: gnuradio.gr.interp_fir_filter_ccf +.. autooldblock:: gnuradio.gr.interp_fir_filter_fcc +.. autooldblock:: gnuradio.gr.interp_fir_filter_fff +.. autooldblock:: gnuradio.gr.interp_fir_filter_fsf +.. autooldblock:: gnuradio.gr.interp_fir_filter_scc +.. autooldblock:: gnuradio.gr.rational_resampler_base_ccc +.. autooldblock:: gnuradio.gr.rational_resampler_base_ccf +.. autooldblock:: gnuradio.gr.rational_resampler_base_fcc +.. autooldblock:: gnuradio.gr.rational_resampler_base_fff +.. autooldblock:: gnuradio.gr.rational_resampler_base_fsf +.. autooldblock:: gnuradio.gr.rational_resampler_base_scc +.. autooldblock:: gnuradio.gr.single_pole_iir_filter_cc +.. autooldblock:: gnuradio.gr.single_pole_iir_filter_ff +.. autooldblock:: gnuradio.gr.moving_average_cc +.. autooldblock:: gnuradio.gr.moving_average_ff +.. autooldblock:: gnuradio.gr.moving_average_ii +.. autooldblock:: gnuradio.gr.moving_average_ss +.. autooldblock:: gnuradio.gr.pfb_arb_resampler_ccf +.. autooldblock:: gnuradio.gr.pfb_channelizer_ccf +.. autooldblock:: gnuradio.gr.pfb_clock_sync_ccf +.. autooldblock:: gnuradio.gr.pfb_clock_sync_fff +.. autooldblock:: gnuradio.gr.pfb_decimator_ccf +.. autooldblock:: gnuradio.gr.pfb_interpolator_ccf diff --git a/docs/sphinx/source/gr/level_blk.rst b/docs/sphinx/source/gr/level_blk.rst index 77ba2270df..d6c565c65d 100644 --- a/docs/sphinx/source/gr/level_blk.rst +++ b/docs/sphinx/source/gr/level_blk.rst @@ -1,26 +1,26 @@ gnuradio.gr: Signal Level Control (AGC) ======================================= -.. autoblock:: gnuradio.gr.agc2_cc -.. autoblock:: gnuradio.gr.agc2_ff -.. autoblock:: gnuradio.gr.agc_cc -.. autoblock:: gnuradio.gr.agc_ff -.. autoblock:: gnuradio.gr.ctcss_squelch_ff -.. autoblock:: gnuradio.gr.dpll_bb -.. autoblock:: gnuradio.gr.feedforward_agc_cc -.. autoblock:: gnuradio.gr.peak_detector2_fb -.. autoblock:: gnuradio.gr.pwr_squelch_cc -.. autoblock:: gnuradio.gr.pwr_squelch_ff -.. autoblock:: gnuradio.gr.regenerate_bb -.. autoblock:: gnuradio.gr.simple_squelch_cc -.. autoblock:: gnuradio.gr.mute_cc -.. autoblock:: gnuradio.gr.mute_ff -.. autoblock:: gnuradio.gr.mute_ii -.. autoblock:: gnuradio.gr.mute_ss -.. autoblock:: gnuradio.gr.peak_detector_fb -.. autoblock:: gnuradio.gr.peak_detector_ib -.. autoblock:: gnuradio.gr.peak_detector_sb -.. autoblock:: gnuradio.gr.sample_and_hold_bb -.. autoblock:: gnuradio.gr.sample_and_hold_ff -.. autoblock:: gnuradio.gr.sample_and_hold_ii -.. autoblock:: gnuradio.gr.sample_and_hold_ss +.. autooldblock:: gnuradio.gr.agc2_cc +.. autooldblock:: gnuradio.gr.agc2_ff +.. autooldblock:: gnuradio.gr.agc_cc +.. autooldblock:: gnuradio.gr.agc_ff +.. autooldblock:: gnuradio.gr.ctcss_squelch_ff +.. autooldblock:: gnuradio.gr.dpll_bb +.. autooldblock:: gnuradio.gr.feedforward_agc_cc +.. autooldblock:: gnuradio.gr.peak_detector2_fb +.. autooldblock:: gnuradio.gr.pwr_squelch_cc +.. autooldblock:: gnuradio.gr.pwr_squelch_ff +.. autooldblock:: gnuradio.gr.regenerate_bb +.. autooldblock:: gnuradio.gr.simple_squelch_cc +.. autooldblock:: gnuradio.gr.mute_cc +.. autooldblock:: gnuradio.gr.mute_ff +.. autooldblock:: gnuradio.gr.mute_ii +.. autooldblock:: gnuradio.gr.mute_ss +.. autooldblock:: gnuradio.gr.peak_detector_fb +.. autooldblock:: gnuradio.gr.peak_detector_ib +.. autooldblock:: gnuradio.gr.peak_detector_sb +.. autooldblock:: gnuradio.gr.sample_and_hold_bb +.. autooldblock:: gnuradio.gr.sample_and_hold_ff +.. autooldblock:: gnuradio.gr.sample_and_hold_ii +.. autooldblock:: gnuradio.gr.sample_and_hold_ss diff --git a/docs/sphinx/source/gr/math_blk.rst b/docs/sphinx/source/gr/math_blk.rst index a2ef51922e..7b9437f995 100644 --- a/docs/sphinx/source/gr/math_blk.rst +++ b/docs/sphinx/source/gr/math_blk.rst @@ -1,59 +1,59 @@ gnuradio.gr: Mathematics ======================== -.. autoblock:: gnuradio.gr.conjugate_cc -.. autoblock:: gnuradio.gr.nlog10_ff -.. autoblock:: gnuradio.gr.rms_cf -.. autoblock:: gnuradio.gr.rms_ff -.. autoblock:: gnuradio.gr.add_cc -.. autoblock:: gnuradio.gr.add_const_cc -.. autoblock:: gnuradio.gr.add_const_ff -.. autoblock:: gnuradio.gr.add_const_ii -.. autoblock:: gnuradio.gr.add_const_sf -.. autoblock:: gnuradio.gr.add_const_ss -.. autoblock:: gnuradio.gr.add_const_vcc -.. autoblock:: gnuradio.gr.add_const_vff -.. autoblock:: gnuradio.gr.add_const_vii -.. autoblock:: gnuradio.gr.add_const_vss -.. autoblock:: gnuradio.gr.add_ff -.. autoblock:: gnuradio.gr.add_ii -.. autoblock:: gnuradio.gr.add_ss -.. autoblock:: gnuradio.gr.and_bb -.. autoblock:: gnuradio.gr.and_const_bb -.. autoblock:: gnuradio.gr.and_const_ii -.. autoblock:: gnuradio.gr.and_const_ss -.. autoblock:: gnuradio.gr.and_ii -.. autoblock:: gnuradio.gr.and_ss -.. autoblock:: gnuradio.gr.divide_cc -.. autoblock:: gnuradio.gr.divide_ff -.. autoblock:: gnuradio.gr.divide_ii -.. autoblock:: gnuradio.gr.divide_ss -.. autoblock:: gnuradio.gr.integrate_cc -.. autoblock:: gnuradio.gr.integrate_ff -.. autoblock:: gnuradio.gr.integrate_ii -.. autoblock:: gnuradio.gr.integrate_ss -.. autoblock:: gnuradio.gr.multiply_cc -.. autoblock:: gnuradio.gr.multiply_const_cc -.. autoblock:: gnuradio.gr.multiply_const_ff -.. autoblock:: gnuradio.gr.multiply_const_ii -.. autoblock:: gnuradio.gr.multiply_const_ss -.. autoblock:: gnuradio.gr.multiply_const_vcc -.. autoblock:: gnuradio.gr.multiply_const_vff -.. autoblock:: gnuradio.gr.multiply_const_vii -.. autoblock:: gnuradio.gr.multiply_const_vss -.. autoblock:: gnuradio.gr.multiply_ff -.. autoblock:: gnuradio.gr.multiply_ii -.. autoblock:: gnuradio.gr.multiply_ss -.. autoblock:: gnuradio.gr.not_bb -.. autoblock:: gnuradio.gr.not_ii -.. autoblock:: gnuradio.gr.not_ss -.. autoblock:: gnuradio.gr.or_bb -.. autoblock:: gnuradio.gr.or_ii -.. autoblock:: gnuradio.gr.or_ss -.. autoblock:: gnuradio.gr.sub_cc -.. autoblock:: gnuradio.gr.sub_ff -.. autoblock:: gnuradio.gr.sub_ii -.. autoblock:: gnuradio.gr.sub_ss -.. autoblock:: gnuradio.gr.xor_bb -.. autoblock:: gnuradio.gr.xor_ii -.. autoblock:: gnuradio.gr.xor_ss +.. autooldblock:: gnuradio.gr.conjugate_cc +.. autooldblock:: gnuradio.gr.nlog10_ff +.. autooldblock:: gnuradio.gr.rms_cf +.. autooldblock:: gnuradio.gr.rms_ff +.. autooldblock:: gnuradio.gr.add_cc +.. autooldblock:: gnuradio.gr.add_const_cc +.. autooldblock:: gnuradio.gr.add_const_ff +.. autooldblock:: gnuradio.gr.add_const_ii +.. autooldblock:: gnuradio.gr.add_const_sf +.. autooldblock:: gnuradio.gr.add_const_ss +.. autooldblock:: gnuradio.gr.add_const_vcc +.. autooldblock:: gnuradio.gr.add_const_vff +.. autooldblock:: gnuradio.gr.add_const_vii +.. autooldblock:: gnuradio.gr.add_const_vss +.. autooldblock:: gnuradio.gr.add_ff +.. autooldblock:: gnuradio.gr.add_ii +.. autooldblock:: gnuradio.gr.add_ss +.. autooldblock:: gnuradio.gr.and_bb +.. autooldblock:: gnuradio.gr.and_const_bb +.. autooldblock:: gnuradio.gr.and_const_ii +.. autooldblock:: gnuradio.gr.and_const_ss +.. autooldblock:: gnuradio.gr.and_ii +.. autooldblock:: gnuradio.gr.and_ss +.. autooldblock:: gnuradio.gr.divide_cc +.. autooldblock:: gnuradio.gr.divide_ff +.. autooldblock:: gnuradio.gr.divide_ii +.. autooldblock:: gnuradio.gr.divide_ss +.. autooldblock:: gnuradio.gr.integrate_cc +.. autooldblock:: gnuradio.gr.integrate_ff +.. autooldblock:: gnuradio.gr.integrate_ii +.. autooldblock:: gnuradio.gr.integrate_ss +.. autooldblock:: gnuradio.gr.multiply_cc +.. autooldblock:: gnuradio.gr.multiply_const_cc +.. autooldblock:: gnuradio.gr.multiply_const_ff +.. autooldblock:: gnuradio.gr.multiply_const_ii +.. autooldblock:: gnuradio.gr.multiply_const_ss +.. autooldblock:: gnuradio.gr.multiply_const_vcc +.. autooldblock:: gnuradio.gr.multiply_const_vff +.. autooldblock:: gnuradio.gr.multiply_const_vii +.. autooldblock:: gnuradio.gr.multiply_const_vss +.. autooldblock:: gnuradio.gr.multiply_ff +.. autooldblock:: gnuradio.gr.multiply_ii +.. autooldblock:: gnuradio.gr.multiply_ss +.. autooldblock:: gnuradio.gr.not_bb +.. autooldblock:: gnuradio.gr.not_ii +.. autooldblock:: gnuradio.gr.not_ss +.. autooldblock:: gnuradio.gr.or_bb +.. autooldblock:: gnuradio.gr.or_ii +.. autooldblock:: gnuradio.gr.or_ss +.. autooldblock:: gnuradio.gr.sub_cc +.. autooldblock:: gnuradio.gr.sub_ff +.. autooldblock:: gnuradio.gr.sub_ii +.. autooldblock:: gnuradio.gr.sub_ss +.. autooldblock:: gnuradio.gr.xor_bb +.. autooldblock:: gnuradio.gr.xor_ii +.. autooldblock:: gnuradio.gr.xor_ss diff --git a/docs/sphinx/source/gr/misc_blk.rst b/docs/sphinx/source/gr/misc_blk.rst index f3bd2d943b..c69293056c 100644 --- a/docs/sphinx/source/gr/misc_blk.rst +++ b/docs/sphinx/source/gr/misc_blk.rst @@ -1,12 +1,12 @@ gnuradio.gr: Miscellaneous Blocks ================================= -.. autoblock:: gnuradio.gr.copy -.. autoblock:: gnuradio.gr.delay -.. autoblock:: gnuradio.gr.kludge_copy -.. autoblock:: gnuradio.gr.nop -.. autoblock:: gnuradio.gr.pa_2x2_phase_combiner -.. autoblock:: gnuradio.gr.repeat -.. autoblock:: gnuradio.gr.threshold_ff -.. autoblock:: gnuradio.gr.throttle -.. autoblock:: gnuradio.gr.channel_model +.. autooldblock:: gnuradio.gr.copy +.. autooldblock:: gnuradio.gr.delay +.. autooldblock:: gnuradio.gr.kludge_copy +.. autooldblock:: gnuradio.gr.nop +.. autooldblock:: gnuradio.gr.pa_2x2_phase_combiner +.. autooldblock:: gnuradio.gr.repeat +.. autooldblock:: gnuradio.gr.threshold_ff +.. autooldblock:: gnuradio.gr.throttle +.. autooldblock:: gnuradio.gr.channel_model diff --git a/docs/sphinx/source/gr/modulation_blk.rst b/docs/sphinx/source/gr/modulation_blk.rst index 7cc54d9dc5..1fff4614ca 100644 --- a/docs/sphinx/source/gr/modulation_blk.rst +++ b/docs/sphinx/source/gr/modulation_blk.rst @@ -1,6 +1,6 @@ gnuradio.gr: Modulation ======================= -.. autoblock:: gnuradio.gr.cpfsk_bc -.. autoblock:: gnuradio.gr.frequency_modulator_fc -.. autoblock:: gnuradio.gr.phase_modulator_fc +.. autooldblock:: gnuradio.gr.cpfsk_bc +.. autooldblock:: gnuradio.gr.frequency_modulator_fc +.. autooldblock:: gnuradio.gr.phase_modulator_fc diff --git a/docs/sphinx/source/gr/sink_blk.rst b/docs/sphinx/source/gr/sink_blk.rst index 8e5c7a4036..7608ff09b0 100644 --- a/docs/sphinx/source/gr/sink_blk.rst +++ b/docs/sphinx/source/gr/sink_blk.rst @@ -1,25 +1,25 @@ gnuradio.gr: Signal Sinks ========================= -.. autoblock:: gnuradio.gr.bin_statistics_f -.. autoblock:: gnuradio.gr.check_counting_s -.. autoblock:: gnuradio.gr.check_lfsr_32k_s -.. autoblock:: gnuradio.gr.framer_sink_1 -.. autoblock:: gnuradio.gr.null_sink -.. autoblock:: gnuradio.gr.packet_sink -.. autoblock:: gnuradio.gr.probe_avg_mag_sqrd_c -.. autoblock:: gnuradio.gr.probe_avg_mag_sqrd_cf -.. autoblock:: gnuradio.gr.probe_avg_mag_sqrd_f -.. autoblock:: gnuradio.gr.probe_signal_f -.. autoblock:: gnuradio.gr.vector_sink_b -.. autoblock:: gnuradio.gr.vector_sink_c -.. autoblock:: gnuradio.gr.vector_sink_f -.. autoblock:: gnuradio.gr.vector_sink_i -.. autoblock:: gnuradio.gr.vector_sink_s -.. autoblock:: gnuradio.gr.file_descriptor_sink -.. autoblock:: gnuradio.gr.file_sink -.. autoblock:: gnuradio.gr.histo_sink_f -.. autoblock:: gnuradio.gr.message_sink -.. autoblock:: gnuradio.gr.oscope_sink_f -.. autoblock:: gnuradio.gr.udp_sink -.. autoblock:: gnuradio.gr.wavfile_sink +.. autooldblock:: gnuradio.gr.bin_statistics_f +.. autooldblock:: gnuradio.gr.check_counting_s +.. autooldblock:: gnuradio.gr.check_lfsr_32k_s +.. autooldblock:: gnuradio.gr.framer_sink_1 +.. autooldblock:: gnuradio.gr.null_sink +.. autooldblock:: gnuradio.gr.packet_sink +.. autooldblock:: gnuradio.gr.probe_avg_mag_sqrd_c +.. autooldblock:: gnuradio.gr.probe_avg_mag_sqrd_cf +.. autooldblock:: gnuradio.gr.probe_avg_mag_sqrd_f +.. autooldblock:: gnuradio.gr.probe_signal_f +.. autooldblock:: gnuradio.gr.vector_sink_b +.. autooldblock:: gnuradio.gr.vector_sink_c +.. autooldblock:: gnuradio.gr.vector_sink_f +.. autooldblock:: gnuradio.gr.vector_sink_i +.. autooldblock:: gnuradio.gr.vector_sink_s +.. autooldblock:: gnuradio.gr.file_descriptor_sink +.. autooldblock:: gnuradio.gr.file_sink +.. autooldblock:: gnuradio.gr.histo_sink_f +.. autooldblock:: gnuradio.gr.message_sink +.. autooldblock:: gnuradio.gr.oscope_sink_f +.. autooldblock:: gnuradio.gr.udp_sink +.. autooldblock:: gnuradio.gr.wavfile_sink diff --git a/docs/sphinx/source/gr/slicedice_blk.rst b/docs/sphinx/source/gr/slicedice_blk.rst index 0bb5719ea6..e845627aad 100644 --- a/docs/sphinx/source/gr/slicedice_blk.rst +++ b/docs/sphinx/source/gr/slicedice_blk.rst @@ -1,14 +1,14 @@ gnuradio.gr: Slicing and Dicing Streams ======================================= -.. autoblock:: gnuradio.gr.deinterleave -.. autoblock:: gnuradio.gr.head -.. autoblock:: gnuradio.gr.interleave -.. autoblock:: gnuradio.gr.keep_one_in_n -.. autoblock:: gnuradio.gr.skiphead -.. autoblock:: gnuradio.gr.stream_to_streams -.. autoblock:: gnuradio.gr.stream_to_vector -.. autoblock:: gnuradio.gr.streams_to_stream -.. autoblock:: gnuradio.gr.streams_to_vector -.. autoblock:: gnuradio.gr.vector_to_stream -.. autoblock:: gnuradio.gr.vector_to_streams +.. autooldblock:: gnuradio.gr.deinterleave +.. autooldblock:: gnuradio.gr.head +.. autooldblock:: gnuradio.gr.interleave +.. autooldblock:: gnuradio.gr.keep_one_in_n +.. autooldblock:: gnuradio.gr.skiphead +.. autooldblock:: gnuradio.gr.stream_to_streams +.. autooldblock:: gnuradio.gr.stream_to_vector +.. autooldblock:: gnuradio.gr.streams_to_stream +.. autooldblock:: gnuradio.gr.streams_to_vector +.. autooldblock:: gnuradio.gr.vector_to_stream +.. autooldblock:: gnuradio.gr.vector_to_streams diff --git a/docs/sphinx/source/gr/source_blk.rst b/docs/sphinx/source/gr/source_blk.rst index e6e24e1b54..df873bcf74 100644 --- a/docs/sphinx/source/gr/source_blk.rst +++ b/docs/sphinx/source/gr/source_blk.rst @@ -1,26 +1,26 @@ gnuradio.gr: Signal Sources =========================== -.. autoblock:: gnuradio.gr.glfsr_source_b -.. autoblock:: gnuradio.gr.glfsr_source_f -.. autoblock:: gnuradio.gr.lfsr_32k_source_s -.. autoblock:: gnuradio.gr.null_source -.. autoblock:: gnuradio.gr.noise_source_c -.. autoblock:: gnuradio.gr.noise_source_f -.. autoblock:: gnuradio.gr.noise_source_i -.. autoblock:: gnuradio.gr.noise_source_s -.. autoblock:: gnuradio.gr.sig_source_c -.. autoblock:: gnuradio.gr.sig_source_f -.. autoblock:: gnuradio.gr.sig_source_i -.. autoblock:: gnuradio.gr.sig_source_s -.. autoblock:: gnuradio.gr.vector_source_b -.. autoblock:: gnuradio.gr.vector_source_c -.. autoblock:: gnuradio.gr.vector_source_f -.. autoblock:: gnuradio.gr.vector_source_i -.. autoblock:: gnuradio.gr.vector_source_s -.. autoblock:: gnuradio.gr.file_descriptor_source -.. autoblock:: gnuradio.gr.file_source -.. autoblock:: gnuradio.gr.message_source -.. autoblock:: gnuradio.gr.udp_source -.. autoblock:: gnuradio.gr.wavfile_source +.. autooldblock:: gnuradio.gr.glfsr_source_b +.. autooldblock:: gnuradio.gr.glfsr_source_f +.. autooldblock:: gnuradio.gr.lfsr_32k_source_s +.. autooldblock:: gnuradio.gr.null_source +.. autooldblock:: gnuradio.gr.noise_source_c +.. autooldblock:: gnuradio.gr.noise_source_f +.. autooldblock:: gnuradio.gr.noise_source_i +.. autooldblock:: gnuradio.gr.noise_source_s +.. autooldblock:: gnuradio.gr.sig_source_c +.. autooldblock:: gnuradio.gr.sig_source_f +.. autooldblock:: gnuradio.gr.sig_source_i +.. autooldblock:: gnuradio.gr.sig_source_s +.. autooldblock:: gnuradio.gr.vector_source_b +.. autooldblock:: gnuradio.gr.vector_source_c +.. autooldblock:: gnuradio.gr.vector_source_f +.. autooldblock:: gnuradio.gr.vector_source_i +.. autooldblock:: gnuradio.gr.vector_source_s +.. autooldblock:: gnuradio.gr.file_descriptor_source +.. autooldblock:: gnuradio.gr.file_source +.. autooldblock:: gnuradio.gr.message_source +.. autooldblock:: gnuradio.gr.udp_source +.. autooldblock:: gnuradio.gr.wavfile_source diff --git a/docs/sphinx/source/gr/sync_blk.rst b/docs/sphinx/source/gr/sync_blk.rst index bb2b839741..be9f908f73 100644 --- a/docs/sphinx/source/gr/sync_blk.rst +++ b/docs/sphinx/source/gr/sync_blk.rst @@ -1,9 +1,9 @@ gnuradio.gr: Synchronization ============================ -.. autoblock:: gnuradio.gr.pll_carriertracking_cc -.. autoblock:: gnuradio.gr.pll_freqdet_cf -.. autoblock:: gnuradio.gr.pll_refout_cc -.. autoblock:: gnuradio.gr.pn_correlator_cc -.. autoblock:: gnuradio.gr.simple_correlator -.. autoblock:: gnuradio.gr.simple_framer +.. autooldblock:: gnuradio.gr.pll_carriertracking_cc +.. autooldblock:: gnuradio.gr.pll_freqdet_cf +.. autooldblock:: gnuradio.gr.pll_refout_cc +.. autooldblock:: gnuradio.gr.pn_correlator_cc +.. autooldblock:: gnuradio.gr.simple_correlator +.. autooldblock:: gnuradio.gr.simple_framer diff --git a/docs/sphinx/source/index.rst b/docs/sphinx/source/index.rst index 887271ce00..38d859aafd 100644 --- a/docs/sphinx/source/index.rst +++ b/docs/sphinx/source/index.rst @@ -15,6 +15,7 @@ Core Framework gnuradio.audio gnuradio.trellis gnuradio.wavelet + gnuradio.fft gnuradio.window gnuradio.optfir gnuradio.gr_unittest @@ -32,6 +33,7 @@ Core Framework gnuradio.optfir <optfir/index> gnuradio.trellis <trellis/index> gnuradio.wavelet <wavelet> + gnuradio.fft <fft> gnuradio.window <window/index> gnuradio.qtgui <qtgui/index> gnuradio.wxgui <wxgui/index> diff --git a/docs/sphinx/source/noaa.rst b/docs/sphinx/source/noaa.rst index 06c7078130..65461f99b8 100644 --- a/docs/sphinx/source/noaa.rst +++ b/docs/sphinx/source/noaa.rst @@ -3,6 +3,6 @@ gnuradio.noaa .. automodule:: gnuradio.noaa -.. autoblock:: gnuradio.noaa.hrpt_decoder -.. autoblock:: gnuradio.noaa.hrpt_deframer -.. autoblock:: gnuradio.noaa.hrpt_pll_cf +.. autooldblock:: gnuradio.noaa.hrpt_decoder +.. autooldblock:: gnuradio.noaa.hrpt_deframer +.. autooldblock:: gnuradio.noaa.hrpt_pll_cf diff --git a/docs/sphinx/source/pager/blks.rst b/docs/sphinx/source/pager/blks.rst index 9b5a2ca70d..a36103d1fa 100644 --- a/docs/sphinx/source/pager/blks.rst +++ b/docs/sphinx/source/pager/blks.rst @@ -1,9 +1,9 @@ gnuradio.pager: Signal Processing Blocks ======================================== -.. autoblock:: gnuradio.pager.flex_deinterleave +.. autooldblock:: gnuradio.pager.flex_deinterleave .. autopyblock:: gnuradio.pager.flex_demod -.. autoblock:: gnuradio.pager.flex_frame -.. autoblock:: gnuradio.pager.flex_parse -.. autoblock:: gnuradio.pager.flex_sync -.. autoblock:: gnuradio.pager.slicer_fb +.. autooldblock:: gnuradio.pager.flex_frame +.. autooldblock:: gnuradio.pager.flex_parse +.. autooldblock:: gnuradio.pager.flex_sync +.. autooldblock:: gnuradio.pager.slicer_fb diff --git a/docs/sphinx/source/qtgui/index.rst b/docs/sphinx/source/qtgui/index.rst index c6311d381a..83bdedca89 100644 --- a/docs/sphinx/source/qtgui/index.rst +++ b/docs/sphinx/source/qtgui/index.rst @@ -3,7 +3,7 @@ gnuradio.qtgui .. automodule:: gnuradio.qtgui -.. autoblock:: gnuradio.qtgui.sink_c -.. autoblock:: gnuradio.qtgui.sink_f -.. autoblock:: gnuradio.qtgui.time_sink_c -.. autoblock:: gnuradio.qtgui.time_sink_f +.. autooldblock:: gnuradio.qtgui.sink_c +.. autooldblock:: gnuradio.qtgui.sink_f +.. autooldblock:: gnuradio.qtgui.time_sink_c +.. autooldblock:: gnuradio.qtgui.time_sink_f diff --git a/docs/sphinx/source/trellis/blks.rst b/docs/sphinx/source/trellis/blks.rst index a2eda07d61..d82319bad6 100644 --- a/docs/sphinx/source/trellis/blks.rst +++ b/docs/sphinx/source/trellis/blks.rst @@ -1,62 +1,62 @@ gnuradio.trellis: Signal Processing Blocks ========================================== -.. autoblock:: gnuradio.trellis.constellation_metrics_cf -.. autoblock:: gnuradio.trellis.encoder_bb -.. autoblock:: gnuradio.trellis.encoder_bi -.. autoblock:: gnuradio.trellis.encoder_bs -.. autoblock:: gnuradio.trellis.encoder_ii -.. autoblock:: gnuradio.trellis.encoder_si -.. autoblock:: gnuradio.trellis.encoder_ss -.. autoblock:: gnuradio.trellis.metrics_c -.. autoblock:: gnuradio.trellis.metrics_f -.. autoblock:: gnuradio.trellis.metrics_i -.. autoblock:: gnuradio.trellis.metrics_s -.. autoblock:: gnuradio.trellis.pccc_decoder_b -.. autoblock:: gnuradio.trellis.pccc_decoder_combined_cb -.. autoblock:: gnuradio.trellis.pccc_decoder_combined_ci -.. autoblock:: gnuradio.trellis.pccc_decoder_combined_cs -.. autoblock:: gnuradio.trellis.pccc_decoder_combined_fb -.. autoblock:: gnuradio.trellis.pccc_decoder_combined_fi -.. autoblock:: gnuradio.trellis.pccc_decoder_combined_fs -.. autoblock:: gnuradio.trellis.pccc_decoder_i -.. autoblock:: gnuradio.trellis.pccc_decoder_s -.. autoblock:: gnuradio.trellis.pccc_encoder_bb -.. autoblock:: gnuradio.trellis.pccc_encoder_bi -.. autoblock:: gnuradio.trellis.pccc_encoder_bs -.. autoblock:: gnuradio.trellis.pccc_encoder_ii -.. autoblock:: gnuradio.trellis.pccc_encoder_si -.. autoblock:: gnuradio.trellis.pccc_encoder_ss -.. autoblock:: gnuradio.trellis.permutation -.. autoblock:: gnuradio.trellis.sccc_decoder_b -.. autoblock:: gnuradio.trellis.sccc_decoder_combined_cb -.. autoblock:: gnuradio.trellis.sccc_decoder_combined_ci -.. autoblock:: gnuradio.trellis.sccc_decoder_combined_cs -.. autoblock:: gnuradio.trellis.sccc_decoder_combined_fb -.. autoblock:: gnuradio.trellis.sccc_decoder_combined_fi -.. autoblock:: gnuradio.trellis.sccc_decoder_combined_fs -.. autoblock:: gnuradio.trellis.sccc_decoder_i -.. autoblock:: gnuradio.trellis.sccc_decoder_s -.. autoblock:: gnuradio.trellis.sccc_encoder_bb -.. autoblock:: gnuradio.trellis.sccc_encoder_bi -.. autoblock:: gnuradio.trellis.sccc_encoder_bs -.. autoblock:: gnuradio.trellis.sccc_encoder_ii -.. autoblock:: gnuradio.trellis.sccc_encoder_si -.. autoblock:: gnuradio.trellis.sccc_encoder_ss -.. autoblock:: gnuradio.trellis.siso_combined_f -.. autoblock:: gnuradio.trellis.siso_f -.. autoblock:: gnuradio.trellis.viterbi_b -.. autoblock:: gnuradio.trellis.viterbi_combined_cb -.. autoblock:: gnuradio.trellis.viterbi_combined_ci -.. autoblock:: gnuradio.trellis.viterbi_combined_cs -.. autoblock:: gnuradio.trellis.viterbi_combined_fb -.. autoblock:: gnuradio.trellis.viterbi_combined_fi -.. autoblock:: gnuradio.trellis.viterbi_combined_fs -.. autoblock:: gnuradio.trellis.viterbi_combined_ib -.. autoblock:: gnuradio.trellis.viterbi_combined_ii -.. autoblock:: gnuradio.trellis.viterbi_combined_is -.. autoblock:: gnuradio.trellis.viterbi_combined_sb -.. autoblock:: gnuradio.trellis.viterbi_combined_si -.. autoblock:: gnuradio.trellis.viterbi_combined_ss -.. autoblock:: gnuradio.trellis.viterbi_i -.. autoblock:: gnuradio.trellis.viterbi_s +.. autooldblock:: gnuradio.trellis.constellation_metrics_cf +.. autooldblock:: gnuradio.trellis.encoder_bb +.. autooldblock:: gnuradio.trellis.encoder_bi +.. autooldblock:: gnuradio.trellis.encoder_bs +.. autooldblock:: gnuradio.trellis.encoder_ii +.. autooldblock:: gnuradio.trellis.encoder_si +.. autooldblock:: gnuradio.trellis.encoder_ss +.. autooldblock:: gnuradio.trellis.metrics_c +.. autooldblock:: gnuradio.trellis.metrics_f +.. autooldblock:: gnuradio.trellis.metrics_i +.. autooldblock:: gnuradio.trellis.metrics_s +.. autooldblock:: gnuradio.trellis.pccc_decoder_b +.. autooldblock:: gnuradio.trellis.pccc_decoder_combined_cb +.. autooldblock:: gnuradio.trellis.pccc_decoder_combined_ci +.. autooldblock:: gnuradio.trellis.pccc_decoder_combined_cs +.. autooldblock:: gnuradio.trellis.pccc_decoder_combined_fb +.. autooldblock:: gnuradio.trellis.pccc_decoder_combined_fi +.. autooldblock:: gnuradio.trellis.pccc_decoder_combined_fs +.. autooldblock:: gnuradio.trellis.pccc_decoder_i +.. autooldblock:: gnuradio.trellis.pccc_decoder_s +.. autooldblock:: gnuradio.trellis.pccc_encoder_bb +.. autooldblock:: gnuradio.trellis.pccc_encoder_bi +.. autooldblock:: gnuradio.trellis.pccc_encoder_bs +.. autooldblock:: gnuradio.trellis.pccc_encoder_ii +.. autooldblock:: gnuradio.trellis.pccc_encoder_si +.. autooldblock:: gnuradio.trellis.pccc_encoder_ss +.. autooldblock:: gnuradio.trellis.permutation +.. autooldblock:: gnuradio.trellis.sccc_decoder_b +.. autooldblock:: gnuradio.trellis.sccc_decoder_combined_cb +.. autooldblock:: gnuradio.trellis.sccc_decoder_combined_ci +.. autooldblock:: gnuradio.trellis.sccc_decoder_combined_cs +.. autooldblock:: gnuradio.trellis.sccc_decoder_combined_fb +.. autooldblock:: gnuradio.trellis.sccc_decoder_combined_fi +.. autooldblock:: gnuradio.trellis.sccc_decoder_combined_fs +.. autooldblock:: gnuradio.trellis.sccc_decoder_i +.. autooldblock:: gnuradio.trellis.sccc_decoder_s +.. autooldblock:: gnuradio.trellis.sccc_encoder_bb +.. autooldblock:: gnuradio.trellis.sccc_encoder_bi +.. autooldblock:: gnuradio.trellis.sccc_encoder_bs +.. autooldblock:: gnuradio.trellis.sccc_encoder_ii +.. autooldblock:: gnuradio.trellis.sccc_encoder_si +.. autooldblock:: gnuradio.trellis.sccc_encoder_ss +.. autooldblock:: gnuradio.trellis.siso_combined_f +.. autooldblock:: gnuradio.trellis.siso_f +.. autooldblock:: gnuradio.trellis.viterbi_b +.. autooldblock:: gnuradio.trellis.viterbi_combined_cb +.. autooldblock:: gnuradio.trellis.viterbi_combined_ci +.. autooldblock:: gnuradio.trellis.viterbi_combined_cs +.. autooldblock:: gnuradio.trellis.viterbi_combined_fb +.. autooldblock:: gnuradio.trellis.viterbi_combined_fi +.. autooldblock:: gnuradio.trellis.viterbi_combined_fs +.. autooldblock:: gnuradio.trellis.viterbi_combined_ib +.. autooldblock:: gnuradio.trellis.viterbi_combined_ii +.. autooldblock:: gnuradio.trellis.viterbi_combined_is +.. autooldblock:: gnuradio.trellis.viterbi_combined_sb +.. autooldblock:: gnuradio.trellis.viterbi_combined_si +.. autooldblock:: gnuradio.trellis.viterbi_combined_ss +.. autooldblock:: gnuradio.trellis.viterbi_i +.. autooldblock:: gnuradio.trellis.viterbi_s diff --git a/docs/sphinx/source/video_sdl.rst b/docs/sphinx/source/video_sdl.rst index e4fc5acac3..6be88d788c 100644 --- a/docs/sphinx/source/video_sdl.rst +++ b/docs/sphinx/source/video_sdl.rst @@ -3,5 +3,5 @@ gnuradio.video_sdl .. automodule:: gnuradio.video_sdl -.. autoblock:: gnuradio.video_sdl.sink_s -.. autoblock:: gnuradio.video_sdl.sink_uc +.. autooldblock:: gnuradio.video_sdl.sink_s +.. autooldblock:: gnuradio.video_sdl.sink_uc diff --git a/docs/sphinx/source/vocoder/blks.rst b/docs/sphinx/source/vocoder/blks.rst index ea20bc44be..34eda9d250 100644 --- a/docs/sphinx/source/vocoder/blks.rst +++ b/docs/sphinx/source/vocoder/blks.rst @@ -1,19 +1,19 @@ gnuradio.vocoder ================ -.. autoblock:: gnuradio.vocoder.alaw_decode_bs -.. autoblock:: gnuradio.vocoder.alaw_encode_sb -.. autoblock:: gnuradio.vocoder.codec2_decode_ps -.. autoblock:: gnuradio.vocoder.codec2_encode_sp -.. autoblock:: gnuradio.vocoder.cvsd_decode_bs -.. autoblock:: gnuradio.vocoder.cvsd_encode_sb -.. autoblock:: gnuradio.vocoder.g721_decode_bs -.. autoblock:: gnuradio.vocoder.g721_encode_sb -.. autoblock:: gnuradio.vocoder.g723_24_decode_bs -.. autoblock:: gnuradio.vocoder.g723_24_encode_sb -.. autoblock:: gnuradio.vocoder.g723_40_decode_bs -.. autoblock:: gnuradio.vocoder.g723_40_encode_sb -.. autoblock:: gnuradio.vocoder.gsm_fr_decode_ps -.. autoblock:: gnuradio.vocoder.gsm_fr_encode_sp -.. autoblock:: gnuradio.vocoder.ulaw_decode_bs -.. autoblock:: gnuradio.vocoder.ulaw_encode_sb +.. autooldblock:: gnuradio.vocoder.alaw_decode_bs +.. autooldblock:: gnuradio.vocoder.alaw_encode_sb +.. autooldblock:: gnuradio.vocoder.codec2_decode_ps +.. autooldblock:: gnuradio.vocoder.codec2_encode_sp +.. autooldblock:: gnuradio.vocoder.cvsd_decode_bs +.. autooldblock:: gnuradio.vocoder.cvsd_encode_sb +.. autooldblock:: gnuradio.vocoder.g721_decode_bs +.. autooldblock:: gnuradio.vocoder.g721_encode_sb +.. autooldblock:: gnuradio.vocoder.g723_24_decode_bs +.. autooldblock:: gnuradio.vocoder.g723_24_encode_sb +.. autooldblock:: gnuradio.vocoder.g723_40_decode_bs +.. autooldblock:: gnuradio.vocoder.g723_40_encode_sb +.. autooldblock:: gnuradio.vocoder.gsm_fr_decode_ps +.. autooldblock:: gnuradio.vocoder.gsm_fr_encode_sp +.. autooldblock:: gnuradio.vocoder.ulaw_decode_bs +.. autooldblock:: gnuradio.vocoder.ulaw_encode_sb diff --git a/docs/sphinx/source/wavelet.rst b/docs/sphinx/source/wavelet.rst index 679bab70c0..5236c4dbb2 100644 --- a/docs/sphinx/source/wavelet.rst +++ b/docs/sphinx/source/wavelet.rst @@ -3,6 +3,6 @@ gnuradio.wavelet .. automodule:: gnuradio.wavelet -.. autoblock:: gnuradio.wavelet.squash_ff -.. autoblock:: gnuradio.wavelet.wavelet_ff -.. autoblock:: gnuradio.wavelet.wvps_ff +.. autooldblock:: gnuradio.wavelet.squash_ff +.. autooldblock:: gnuradio.wavelet.wavelet_ff +.. autooldblock:: gnuradio.wavelet.wvps_ff diff --git a/gnuradio-core/CMakeLists.txt b/gnuradio-core/CMakeLists.txt index 0227108446..4e76b3c5a6 100644 --- a/gnuradio-core/CMakeLists.txt +++ b/gnuradio-core/CMakeLists.txt @@ -64,6 +64,7 @@ GR_SET_GLOBAL(GNURADIO_CORE_INCLUDE_DIRS GR_SET_GLOBAL(GNURADIO_CORE_SWIG_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/gruel/src/swig + ${CMAKE_BINARY_DIR}/gruel/src/swig/ ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/swig ${GNURADIO_CORE_INCLUDE_DIRS} ) @@ -109,7 +110,7 @@ CPACK_COMPONENT("core_swig" install( FILES gnuradio-core.conf - DESTINATION ${GR_PKG_CONF_DIR} + DESTINATION ${GR_PREFSDIR} COMPONENT "core_runtime" ) diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index 207d85c4c4..082601d5e1 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -48,9 +48,6 @@ message(STATUS "Loading build date ${BUILD_DATE} into gr_constants...") message(STATUS "Loading version ${VERSION} into gr_constants...") -file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}/${GR_CONF_DIR}" SYSCONFDIR) -file(TO_NATIVE_PATH "${CMAKE_INSTALL_PREFIX}/${GR_PKG_CONF_DIR}" GR_PREFSDIR) - #double escape for windows backslash path separators string(REPLACE "\\" "\\\\" prefix ${prefix}) string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR}) @@ -84,7 +81,6 @@ list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_int.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_short.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_uchar.cc - ${CMAKE_CURRENT_SOURCE_DIR}/gri_glfsr.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_interleaved_short_to_complex.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_int_to_float.cc ${CMAKE_CURRENT_SOURCE_DIR}/gri_short_to_float.cc @@ -104,7 +100,6 @@ list(APPEND test_gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt_nco.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt_vco.cc ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_math.cc - ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_lfsr.cc ) ######################################################################## @@ -143,7 +138,6 @@ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_short.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_uchar.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_lfsr.h - ${CMAKE_CURRENT_SOURCE_DIR}/gri_glfsr.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_interleaved_short_to_complex.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_lfsr_15_1_0.h ${CMAKE_CURRENT_SOURCE_DIR}/gri_lfsr_32k.h @@ -179,14 +173,12 @@ endif(ENABLE_PYTHON) set(gr_core_general_triple_threats complex_vec_test gr_add_ff - gr_additive_scrambler_bb gr_agc_cc gr_agc_ff gr_agc2_cc gr_agc2_ff gr_align_on_samplenumbers_ss gr_bin_statistics_f - gr_bytes_to_syms gr_char_to_float gr_char_to_short gr_check_counting_s @@ -199,9 +191,6 @@ set(gr_core_general_triple_threats gr_cpm gr_ctcss_squelch_ff gr_decode_ccsds_27_fb - gr_diff_decoder_bb - gr_diff_encoder_bb - gr_diff_phasor_cc gr_dpll_bb gr_deinterleave gr_delay @@ -219,18 +208,15 @@ set(gr_core_general_triple_threats gr_float_to_uchar gr_fmdet_cf gr_frequency_modulator_fc - gr_framer_sink_1 - gr_glfsr_source_b - gr_glfsr_source_f gr_head gr_int_to_float gr_interleave gr_interleaved_short_to_complex gr_iqcomp_cc gr_keep_one_in_n + gr_keep_m_in_n gr_kludge_copy gr_lfsr_32k_source_s - gr_map_bb gr_multiply_cc gr_multiply_ff gr_multiply_const_cc @@ -241,13 +227,11 @@ set(gr_core_general_triple_threats gr_null_sink gr_null_source gr_pa_2x2_phase_combiner - gr_packet_sink gr_peak_detector2_fb gr_phase_modulator_fc gr_pll_carriertracking_cc gr_pll_freqdet_cf gr_pll_refout_cc - gr_pn_correlator_cc gr_prefs gr_probe_avg_mag_sqrd_c gr_probe_avg_mag_sqrd_cf @@ -264,7 +248,6 @@ set(gr_core_general_triple_threats gr_short_to_float gr_short_to_char gr_simple_correlator - gr_simple_framer gr_simple_squelch_cc gr_skiphead gr_squelch_base_cc @@ -281,16 +264,16 @@ set(gr_core_general_triple_threats gr_transcendental gr_uchar_to_float gr_vco_f + gr_vector_map gr_vector_to_stream gr_vector_to_streams gr_unpack_k_bits_bb - gr_descrambler_bb - gr_scrambler_bb - gr_probe_density_b + gr_pack_k_bits_bb gr_annotator_alltoall gr_annotator_1to1 + gr_annotator_raw gr_burst_tagger - gr_correlate_access_code_tag_bb + gr_tag_debug ) foreach(file_tt ${gr_core_general_triple_threats}) diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index cd8c279c92..b4ddee29ce 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -37,6 +37,7 @@ #include <gr_stream_to_vector.h> #include <gr_vector_to_stream.h> #include <gr_keep_one_in_n.h> +#include <gr_keep_m_in_n.h> #include <gr_fft_vcc.h> #include <gr_fft_vfc.h> #include <gr_float_to_int.h> @@ -51,9 +52,7 @@ #include <gr_uchar_to_float.h> #include <gr_frequency_modulator_fc.h> #include <gr_phase_modulator_fc.h> -#include <gr_bytes_to_syms.h> #include <gr_simple_correlator.h> -#include <gr_simple_framer.h> #include <gr_align_on_samplenumbers_ss.h> #include <gr_complex_to_xxx.h> #include <gr_complex_to_interleaved_short.h> @@ -82,13 +81,11 @@ #include <gr_conjugate_cc.h> #include <gr_vco_f.h> #include <gr_threshold_ff.h> -#include <gr_packet_sink.h> #include <gr_dpll_bb.h> #include <gr_fmdet_cf.h> #include <gr_pll_freqdet_cf.h> #include <gr_pll_refout_cc.h> #include <gr_pll_carriertracking_cc.h> -#include <gr_pn_correlator_cc.h> #include <gr_probe_avg_mag_sqrd_c.h> #include <gr_probe_avg_mag_sqrd_cf.h> #include <gr_probe_avg_mag_sqrd_f.h> @@ -100,11 +97,7 @@ #include <gr_test_types.h> #include <gr_test.h> #include <gr_unpack_k_bits_bb.h> -#include <gr_diff_phasor_cc.h> -#include <gr_diff_encoder_bb.h> -#include <gr_diff_decoder_bb.h> -#include <gr_framer_sink_1.h> -#include <gr_map_bb.h> +#include <gr_pack_k_bits_bb.h> #include <gr_multiply_cc.h> #include <gr_multiply_ff.h> #include <gr_multiply_const_cc.h> @@ -116,27 +109,23 @@ #include <gr_ctcss_squelch_ff.h> #include <gr_feedforward_agc_cc.h> #include <gr_bin_statistics_f.h> -#include <gr_glfsr_source_b.h> -#include <gr_glfsr_source_f.h> #include <gr_peak_detector2_fb.h> #include <gr_repeat.h> #include <gr_cpfsk_bc.h> #include <gr_encode_ccsds_27_bb.h> #include <gr_decode_ccsds_27_fb.h> -#include <gr_descrambler_bb.h> -#include <gr_scrambler_bb.h> -#include <gr_probe_density_b.h> #include <gr_rail_ff.h> #include <gr_stretch_ff.h> #include <gr_copy.h> -#include <gr_additive_scrambler_bb.h> #include <complex_vec_test.h> #include <gr_annotator_alltoall.h> #include <gr_annotator_1to1.h> +#include <gr_annotator_raw.h> #include <gr_burst_tagger.h> #include <gr_cpm.h> -#include <gr_correlate_access_code_tag_bb.h> +#include <gr_vector_map.h> #include <gr_add_ff.h> +#include <gr_tag_debug.h> %} %include "gri_control_loop.i" @@ -154,6 +143,7 @@ %include "gr_stream_to_vector.i" %include "gr_vector_to_stream.i" %include "gr_keep_one_in_n.i" +%include "gr_keep_m_in_n.i" %include "gr_fft_vcc.i" %include "gr_fft_vfc.i" %include "gr_float_to_int.i" @@ -168,9 +158,7 @@ %include "gr_uchar_to_float.i" %include "gr_frequency_modulator_fc.i" %include "gr_phase_modulator_fc.i" -%include "gr_bytes_to_syms.i" %include "gr_simple_correlator.i" -%include "gr_simple_framer.i" %include "gr_align_on_samplenumbers_ss.i" %include "gr_complex_to_xxx.i" %include "gr_complex_to_interleaved_short.i" @@ -199,13 +187,11 @@ %include "gr_conjugate_cc.i" %include "gr_vco_f.i" %include "gr_threshold_ff.i" -%include "gr_packet_sink.i" %include "gr_dpll_bb.i" %include "gr_fmdet_cf.i" %include "gr_pll_freqdet_cf.i" %include "gr_pll_refout_cc.i" %include "gr_pll_carriertracking_cc.i" -%include "gr_pn_correlator_cc.i" %include "gr_probe_avg_mag_sqrd_c.i" %include "gr_probe_avg_mag_sqrd_cf.i" %include "gr_probe_avg_mag_sqrd_f.i" @@ -217,11 +203,7 @@ %include "gr_test_types.h" %include "gr_test.i" %include "gr_unpack_k_bits_bb.i" -%include "gr_diff_phasor_cc.i" -%include "gr_diff_encoder_bb.i" -%include "gr_diff_decoder_bb.i" -%include "gr_framer_sink_1.i" -%include "gr_map_bb.i" +%include "gr_pack_k_bits_bb.i" %include "gr_multiply_cc.i" %include "gr_multiply_ff.i" %include "gr_multiply_const_cc.i" @@ -233,24 +215,20 @@ %include "gr_ctcss_squelch_ff.i" %include "gr_feedforward_agc_cc.i" %include "gr_bin_statistics_f.i" -%include "gr_glfsr_source_b.i" -%include "gr_glfsr_source_f.i" %include "gr_peak_detector2_fb.i" %include "gr_repeat.i" %include "gr_cpfsk_bc.i" %include "gr_encode_ccsds_27_bb.i" %include "gr_decode_ccsds_27_fb.i" -%include "gr_descrambler_bb.i" -%include "gr_scrambler_bb.i" -%include "gr_probe_density_b.i" %include "gr_rail_ff.i" %include "gr_stretch_ff.i" %include "gr_copy.i" -%include "gr_additive_scrambler_bb.i" %include "complex_vec_test.i" %include "gr_annotator_alltoall.i" %include "gr_annotator_1to1.i" +%include "gr_annotator_raw.i" %include "gr_burst_tagger.i" %include "gr_cpm.i" -%include "gr_correlate_access_code_tag_bb.i" +%include "gr_vector_map.i" %include "gr_add_ff.i" +%include "gr_tag_debug.i" diff --git a/gnuradio-core/src/lib/general/general_generated.i b/gnuradio-core/src/lib/general/general_generated.i index 89b7e1776e..43828e7f71 100644 --- a/gnuradio-core/src/lib/general/general_generated.i +++ b/gnuradio-core/src/lib/general/general_generated.i @@ -18,12 +18,6 @@ #include <gr_add_vff.h> #include <gr_add_vii.h> #include <gr_add_vss.h> -#include <gr_chunks_to_symbols_bc.h> -#include <gr_chunks_to_symbols_bf.h> -#include <gr_chunks_to_symbols_ic.h> -#include <gr_chunks_to_symbols_if.h> -#include <gr_chunks_to_symbols_sc.h> -#include <gr_chunks_to_symbols_sf.h> #include <gr_divide_cc.h> #include <gr_divide_ff.h> #include <gr_divide_ii.h> @@ -100,12 +94,6 @@ %include <gr_add_vff.i> %include <gr_add_vii.i> %include <gr_add_vss.i> -%include <gr_chunks_to_symbols_bc.i> -%include <gr_chunks_to_symbols_bf.i> -%include <gr_chunks_to_symbols_ic.i> -%include <gr_chunks_to_symbols_if.i> -%include <gr_chunks_to_symbols_sc.i> -%include <gr_chunks_to_symbols_sf.i> %include <gr_divide_cc.i> %include <gr_divide_ff.i> %include <gr_divide_ii.i> diff --git a/gnuradio-core/src/lib/general/gr_add_ff.cc b/gnuradio-core/src/lib/general/gr_add_ff.cc index 2e45673d3b..5f6676bb7b 100644 --- a/gnuradio-core/src/lib/general/gr_add_ff.cc +++ b/gnuradio-core/src/lib/general/gr_add_ff.cc @@ -42,7 +42,7 @@ gr_add_ff::gr_add_ff (size_t vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc deleted file mode 100644 index 35cbb9572f..0000000000 --- a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_additive_scrambler_bb.h> -#include <gr_io_signature.h> - -gr_additive_scrambler_bb_sptr -gr_make_additive_scrambler_bb(int mask, int seed, int len, int count) -{ - return gnuradio::get_initial_sptr(new gr_additive_scrambler_bb(mask, seed, len, count)); -} - -gr_additive_scrambler_bb::gr_additive_scrambler_bb(int mask, int seed, int len, int count) - : gr_sync_block("additive_scrambler_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_lfsr(mask, seed, len), - d_count(count), - d_bits(0) -{ -} - -int -gr_additive_scrambler_bb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) { - out[i] = in[i]^d_lfsr.next_bit(); - if (d_count > 0) { - if (++d_bits == d_count) { - d_lfsr.reset(); - d_bits = 0; - } - } - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h deleted file mode 100644 index 1c336306d6..0000000000 --- a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_ADDITIVE_SCRAMBLER_BB_H -#define INCLUDED_GR_ADDITIVE_SCRAMBLER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include "gri_lfsr.h" - -class gr_additive_scrambler_bb; -typedef boost::shared_ptr<gr_additive_scrambler_bb> gr_additive_scrambler_bb_sptr; - -GR_CORE_API gr_additive_scrambler_bb_sptr gr_make_additive_scrambler_bb(int mask, int seed, int len, int count=0); - -/*! - * Scramble an input stream using an LFSR. This block works on the LSB only - * of the input data stream, i.e., on an "unpacked binary" stream, and - * produces the same format on its output. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * \param count Number of bits after which shift register is reset, 0=never - * - * The scrambler works by XORing the incoming bit stream by the output of - * the LFSR. Optionally, after 'count' bits have been processed, the shift - * register is reset to the seed value. This allows processing fixed length - * vectors of samples. - * - * \ingroup coding_blk - */ - -class GR_CORE_API gr_additive_scrambler_bb : public gr_sync_block -{ - friend GR_CORE_API gr_additive_scrambler_bb_sptr gr_make_additive_scrambler_bb(int mask, int seed, int len, int count); - - gri_lfsr d_lfsr; - int d_count; - int d_bits; - - gr_additive_scrambler_bb(int mask, int seed, int len, int count); - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_ADDITIVE_SCRAMBLER_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i deleted file mode 100644 index acf9e8c47e..0000000000 --- a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,additive_scrambler_bb); - -gr_additive_scrambler_bb_sptr gr_make_additive_scrambler_bb(int mask, int seed, int len, int count=0); - -class gr_additive_scrambler_bb : public gr_sync_block -{ -private: - gr_additive_scrambler_bb(int mask, int seed, int len, int count); -}; diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.cc b/gnuradio-core/src/lib/general/gr_annotator_raw.cc new file mode 100644 index 0000000000..e1ae73efb6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_raw.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_annotator_raw.h> +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> +#include <stdexcept> + +using namespace pmt; + +gr_annotator_raw_sptr +gr_make_annotator_raw(size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr(new gr_annotator_raw + (sizeof_stream_item)); +} + +gr_annotator_raw::gr_annotator_raw(size_t sizeof_stream_item) + : gr_sync_block("annotator_raw", + gr_make_io_signature(1, 1, sizeof_stream_item), + gr_make_io_signature(1, 1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item) +{ + set_tag_propagation_policy(TPP_ONE_TO_ONE); + set_relative_rate(1.0); +} + +void gr_annotator_raw::add_tag(uint64_t offset, pmt_t key, pmt_t val) +{ + gruel::scoped_lock l(d_mutex); + + gr_tag_t tag; + tag.srcid = pmt::pmt_intern(d_name); + tag.key = key; + tag.value = val; + tag.offset = offset; + + // add our new tag + d_queued_tags.push_back(tag); + // make sure our tags are in offset order + std::sort(d_queued_tags.begin(), d_queued_tags.end(), + gr_tag_t::offset_compare); + // make sure we are not adding an item in the past! + if(tag.offset > nitems_read(0)) { + throw std::runtime_error("gr_annotator_raw::add_tag: item added too far in the past\n."); + } +} + +gr_annotator_raw::~gr_annotator_raw() +{ +} + +int +gr_annotator_raw::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock l(d_mutex); + + const char *in = (const char*)input_items[0]; + char *out = (char*)output_items[0]; + + uint64_t start_N = nitems_read(0); + uint64_t end_N = start_N + (uint64_t)(noutput_items); + + // locate queued tags that fall in this range and insert them when appropriate + std::vector<gr_tag_t>::iterator i = d_queued_tags.begin(); + while( i != d_queued_tags.end() ) { + if( (*i).offset >= start_N && (*i).offset < end_N) { + add_item_tag(0, (*i).offset,(*i).key, (*i).value, (*i).srcid); + i = d_queued_tags.erase(i); + } + else { + break; + } + } + + // copy data across + memcpy(out, in, noutput_items*d_itemsize); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.h b/gnuradio-core/src/lib/general/gr_annotator_raw.h new file mode 100644 index 0000000000..8a6c3f6c02 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_raw.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_ANNOTATOR_RAW_H +#define INCLUDED_GR_ANNOTATOR_RAW_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/pmt.h> +#include <gruel/thread.h> + +class gr_annotator_raw; +typedef boost::shared_ptr<gr_annotator_raw> gr_annotator_raw_sptr; + +// public constructor +GR_CORE_API gr_annotator_raw_sptr +gr_make_annotator_raw(size_t sizeof_stream_item); + +/*! + * \brief raw stream annotator testing block. + * + * This block creates arbitrary tags to be sent downstream + * blocks to be sent are set manually via accessor methods and are sent only once. + * + * This block is intended for testing of tag related blocks + */ +class GR_CORE_API gr_annotator_raw : public gr_sync_block +{ + public: + ~gr_annotator_raw(); + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // insert a tag to be added + void add_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t val); + +protected: + gr_annotator_raw(size_t sizeof_stream_item); + + private: + size_t d_itemsize; + std::vector<gr_tag_t> d_queued_tags; + gruel::mutex d_mutex; + + friend GR_CORE_API gr_annotator_raw_sptr + gr_make_annotator_raw(size_t sizeof_stream_item); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_map_bb.i b/gnuradio-core/src/lib/general/gr_annotator_raw.i index 9c8bff6447..85777ef5d4 100644 --- a/gnuradio-core/src/lib/general/gr_map_bb.i +++ b/gnuradio-core/src/lib/general/gr_annotator_raw.i @@ -1,32 +1,26 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. - * + * Copyright 2010-2011 Free Software Foundation, Inc. + * * This file is part of GNU Radio - * + * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. - * + * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,map_bb); - -gr_map_bb_sptr gr_make_map_bb (const std::vector<int> &map); - -class gr_map_bb : public gr_sync_block -{ - private: - gr_map_bb (const std::vector<int> &map); -}; +GR_SWIG_BLOCK_MAGIC(gr,annotator_raw); +%include <pmt_swig.i> +%include <gr_annotator_raw.h> diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc deleted file mode 100644 index 7dafa29f99..0000000000 --- a/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_bytes_to_syms.h> -#include <gr_io_signature.h> -#include <assert.h> - -static const int BITS_PER_BYTE = 8; - -gr_bytes_to_syms_sptr -gr_make_bytes_to_syms () -{ - return gnuradio::get_initial_sptr(new gr_bytes_to_syms ()); -} - -gr_bytes_to_syms::gr_bytes_to_syms () - : gr_sync_interpolator ("bytes_to_syms", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (float)), - BITS_PER_BYTE) -{ -} - -int -gr_bytes_to_syms::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (unsigned char *) input_items[0]; - float *out = (float *) output_items[0]; - - assert (noutput_items % BITS_PER_BYTE == 0); - - for (int i = 0; i < noutput_items / BITS_PER_BYTE; i++){ - int x = in[i]; - - *out++ = (((x >> 7) & 0x1) << 1) - 1; - *out++ = (((x >> 6) & 0x1) << 1) - 1; - *out++ = (((x >> 5) & 0x1) << 1) - 1; - *out++ = (((x >> 4) & 0x1) << 1) - 1; - *out++ = (((x >> 3) & 0x1) << 1) - 1; - *out++ = (((x >> 2) & 0x1) << 1) - 1; - *out++ = (((x >> 1) & 0x1) << 1) - 1; - *out++ = (((x >> 0) & 0x1) << 1) - 1; - } - - return noutput_items; -} - - - diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.h b/gnuradio-core/src/lib/general/gr_bytes_to_syms.h deleted file mode 100644 index 23e5c6b91b..0000000000 --- a/gnuradio-core/src/lib/general/gr_bytes_to_syms.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_BYTES_TO_SYMS_H -#define INCLUDED_GR_BYTES_TO_SYMS_H - -#include <gr_core_api.h> -#include <gr_sync_interpolator.h> - -class gr_bytes_to_syms; -typedef boost::shared_ptr<gr_bytes_to_syms> gr_bytes_to_syms_sptr; - -GR_CORE_API gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); - -/*! - * \brief Convert stream of bytes to stream of +/- 1 symbols - * \ingroup converter_blk - * - * input: stream of bytes; output: stream of float - * - * This block is deprecated. - * - * The combination of gr_packed_to_unpacked_bb followed by - * gr_chunks_to_symbols_bf or gr_chunks_to_symbols_bc handles the - * general case of mapping from a stream of bytes into arbitrary float - * or complex symbols. - * - * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, - * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. - */ -class GR_CORE_API gr_bytes_to_syms : public gr_sync_interpolator -{ - friend GR_CORE_API gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); - - gr_bytes_to_syms (); - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_BYTES_TO_SYMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_char_to_float.cc b/gnuradio-core/src/lib/general/gr_char_to_float.cc index aec7ad8522..f63aa5b169 100644 --- a/gnuradio-core/src/lib/general/gr_char_to_float.cc +++ b/gnuradio-core/src/lib/general/gr_char_to_float.cc @@ -42,7 +42,7 @@ gr_char_to_float::gr_char_to_float (size_t vlen, float scale) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } float diff --git a/gnuradio-core/src/lib/general/gr_char_to_short.cc b/gnuradio-core/src/lib/general/gr_char_to_short.cc index c20d6cd888..bb9bd8909e 100644 --- a/gnuradio-core/src/lib/general/gr_char_to_short.cc +++ b/gnuradio-core/src/lib/general/gr_char_to_short.cc @@ -42,7 +42,7 @@ gr_char_to_short::gr_char_to_short (size_t vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(char); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc index 3b1fbf9acd..cdf6d7f3a6 100644 --- a/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc @@ -45,7 +45,7 @@ gr_complex_to_float::gr_complex_to_float (unsigned int vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int @@ -106,7 +106,7 @@ gr_complex_to_real::gr_complex_to_real (unsigned int vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int @@ -146,7 +146,7 @@ gr_complex_to_imag::gr_complex_to_imag (unsigned int vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int @@ -186,7 +186,7 @@ gr_complex_to_mag::gr_complex_to_mag (unsigned int vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int @@ -220,7 +220,7 @@ gr_complex_to_mag_squared::gr_complex_to_mag_squared (unsigned int vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int @@ -258,7 +258,7 @@ gr_complex_to_arg::gr_complex_to_arg (unsigned int vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.cc b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc index aaa7f490c7..94ac3e162b 100644 --- a/gnuradio-core/src/lib/general/gr_conjugate_cc.cc +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc @@ -43,7 +43,7 @@ gr_conjugate_cc::gr_conjugate_cc () { const int alignment_multiple = volk_get_alignment() / sizeof(gr_complex); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc deleted file mode 100644 index 73ded3c8b3..0000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006,2010,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_correlate_access_code_tag_bb.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <gr_count_bits.h> -#include <cstdio> -#include <iostream> - -#define VERBOSE 0 - - -gr_correlate_access_code_tag_bb_sptr -gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, const std::string &tag_name) -{ - return gnuradio::get_initial_sptr(new gr_correlate_access_code_tag_bb (access_code, threshold, tag_name)); -} - - -gr_correlate_access_code_tag_bb::gr_correlate_access_code_tag_bb ( - const std::string &access_code, int threshold, const std::string &tag_name) - : gr_sync_block ("correlate_access_code_tag_bb", - gr_make_io_signature (1, 1, sizeof(char)), - gr_make_io_signature (1, 1, sizeof(char))), - d_data_reg(0), d_mask(0), - d_threshold(threshold), d_len(0) - -{ - if (!set_access_code(access_code)){ - fprintf(stderr, "gr_correlate_access_code_tag_bb: access_code is > 64 bits\n"); - throw std::out_of_range ("access_code is > 64 bits"); - } - - std::stringstream str; - str << name() << unique_id(); - d_me = pmt::pmt_string_to_symbol(str.str()); - d_key = pmt::pmt_string_to_symbol(tag_name); -} - -gr_correlate_access_code_tag_bb::~gr_correlate_access_code_tag_bb () -{ -} - -bool -gr_correlate_access_code_tag_bb::set_access_code( - const std::string &access_code) -{ - d_len = access_code.length(); // # of bytes in string - if (d_len > 64) - return false; - - // set len top bits to 1. - d_mask = ((~0ULL) >> (64 - d_len)) << (64 - d_len); - - d_access_code = 0; - for (unsigned i=0; i < 64; i++){ - d_access_code <<= 1; - if (i < d_len) - d_access_code |= access_code[i] & 1; // look at LSB only - } - - return true; -} - -int -gr_correlate_access_code_tag_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - uint64_t abs_out_sample_cnt = nitems_written(0); - - for (int i = 0; i < noutput_items; i++){ - - out[i] = in[i]; - - // compute hamming distance between desired access code and current data - unsigned long long wrong_bits = 0; - unsigned int nwrong = d_threshold+1; - int new_flag = 0; - - wrong_bits = (d_data_reg ^ d_access_code) & d_mask; - nwrong = gr_count_bits64(wrong_bits); - - // test for access code with up to threshold errors - new_flag = (nwrong <= d_threshold); - - // shift in new data and new flag - d_data_reg = (d_data_reg << 1) | (in[i] & 0x1); - if (new_flag) { - if(VERBOSE) std::cout << "writing tag at sample " << abs_out_sample_cnt + i << std::endl; - add_item_tag(0, //stream ID - abs_out_sample_cnt + i - 64 + d_len, //sample - d_key, //frame info - pmt::pmt_t(), //data (unused) - d_me //block src id - ); - } - } - - return noutput_items; -} - diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h deleted file mode 100644 index 345d3004a5..0000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006,2011 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_gr_correlate_access_code_tag_bb_H -#define INCLUDED_gr_correlate_access_code_tag_bb_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include <string> - -class gr_correlate_access_code_tag_bb; -typedef boost::shared_ptr<gr_correlate_access_code_tag_bb> gr_correlate_access_code_tag_bb_sptr; - -/*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - * \param tag_name key of the tag inserted into the tag stream - */ -GR_CORE_API gr_correlate_access_code_tag_bb_sptr -gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, - const std::string &tag_name); - -/*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup sync_blk - * - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: unaltered stream of bits (plus tags) - * - * This block annotates the input stream with tags. The tags have key - * name [tag_name], specified in the constructor. Used for searching - * an input data stream for preambles, etc. - */ -class GR_CORE_API gr_correlate_access_code_tag_bb : public gr_sync_block -{ - friend GR_CORE_API gr_correlate_access_code_tag_bb_sptr - gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, - const std::string &tag_name); - private: - unsigned long long d_access_code; // access code to locate start of packet - // access code is left justified in the word - unsigned long long d_data_reg; // used to look for access_code - unsigned long long d_mask; // masks access_code bits (top N bits are set where - // N is the number of bits in the access code) - unsigned int d_threshold; // how many bits may be wrong in sync vector - unsigned int d_len; //the length of the access code - - pmt::pmt_t d_key, d_me; //d_key is the tag name, d_me is the block name + unique ID - - protected: - gr_correlate_access_code_tag_bb(const std::string &access_code, int threshold, - const std::string &tag_name); - - public: - ~gr_correlate_access_code_tag_bb(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - - /*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - */ - bool set_access_code (const std::string &access_code); -}; - -#endif /* INCLUDED_gr_correlate_access_code_tag_bb_H */ diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i deleted file mode 100644 index f7ca4bea7b..0000000000 --- a/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,correlate_access_code_tag_bb); - -/*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - * \param threshold maximum number of bits that may be wrong - */ -gr_correlate_access_code_tag_bb_sptr -gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, const std::string &tag_name) - throw(std::out_of_range); - -/*! - * \brief Examine input for specified access code, one bit at a time. - * \ingroup block - * - * input: stream of bits, 1 bit per input byte (data in LSB) - * output: stream of bits, 2 bits per output byte (data in LSB, flag in next higher bit) - * - * Each output byte contains two valid bits, the data bit, and the - * flag bit. The LSB (bit 0) is the data bit, and is the original - * input data, delayed 64 bits. Bit 1 is the - * flag bit and is 1 if the corresponding data bit is the first data - * bit following the access code. Otherwise the flag bit is 0. - */ -class gr_correlate_access_code_tag_bb : public gr_sync_block -{ - friend gr_correlate_access_code_tag_bb_sptr - gr_make_correlate_access_code_tag_bb (const std::string &access_code, int threshold, const std::string &tag_name); - protected: - gr_correlate_access_code_tag_bb(const std::string &access_code, int threshold, const std::string &tag_name); - - public: - ~gr_correlate_access_code_tag_bb(); - - /*! - * \param access_code is represented with 1 byte per bit, e.g., "010101010111000100" - */ - bool set_access_code (const std::string &access_code); -}; diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.cc b/gnuradio-core/src/lib/general/gr_descrambler_bb.cc deleted file mode 100644 index b5ae28fa97..0000000000 --- a/gnuradio-core/src/lib/general/gr_descrambler_bb.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_descrambler_bb.h> -#include <gr_io_signature.h> - -gr_descrambler_bb_sptr -gr_make_descrambler_bb(int mask, int seed, int len) -{ - return gnuradio::get_initial_sptr(new gr_descrambler_bb(mask, seed, len)); -} - -gr_descrambler_bb::gr_descrambler_bb(int mask, int seed, int len) - : gr_sync_block("descrambler_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_lfsr(mask, seed, len) -{ -} - -int -gr_descrambler_bb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) - out[i] = d_lfsr.next_bit_descramble(in[i]); - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.h b/gnuradio-core/src/lib/general/gr_descrambler_bb.h deleted file mode 100644 index 333593caaf..0000000000 --- a/gnuradio-core/src/lib/general/gr_descrambler_bb.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_DESCRAMBLER_BB_H -#define INCLUDED_GR_DESCRAMBLER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include "gri_lfsr.h" - -class gr_descrambler_bb; -typedef boost::shared_ptr<gr_descrambler_bb> gr_descrambler_bb_sptr; - -GR_CORE_API gr_descrambler_bb_sptr gr_make_descrambler_bb(int mask, int seed, int len); - -/*! - * Descramble an input stream using an LFSR. This block works on the LSB only - * of the input data stream, i.e., on an "unpacked binary" stream, and - * produces the same format on its output. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * - * \ingroup coding_blk - */ - -class GR_CORE_API gr_descrambler_bb : public gr_sync_block -{ - friend GR_CORE_API gr_descrambler_bb_sptr gr_make_descrambler_bb(int mask, int seed, int len); - - gri_lfsr d_lfsr; - - gr_descrambler_bb(int mask, int seed, int len); - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_DESCRAMBLER_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.i b/gnuradio-core/src/lib/general/gr_descrambler_bb.i deleted file mode 100644 index c6cd0a2852..0000000000 --- a/gnuradio-core/src/lib/general/gr_descrambler_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,descrambler_bb); - -gr_descrambler_bb_sptr gr_make_descrambler_bb(int mask, int seed, int len); - -class gr_descrambler_bb : public gr_sync_block -{ -private: - gr_descrambler_bb(int mask, int seed, int len); -}; diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc deleted file mode 100644 index 74324a62ea..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_diff_decoder_bb.h> -#include <gr_io_signature.h> - -gr_diff_decoder_bb_sptr -gr_make_diff_decoder_bb (unsigned int modulus) -{ - return gnuradio::get_initial_sptr(new gr_diff_decoder_bb(modulus)); -} - -gr_diff_decoder_bb::gr_diff_decoder_bb (unsigned int modulus) - : gr_sync_block ("diff_decoder_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_modulus(modulus) -{ - set_history(2); // need to look at two inputs -} - -int -gr_diff_decoder_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - in += 1; // ensure that in[-1] is valid - - unsigned modulus = d_modulus; - - for (int i = 0; i < noutput_items; i++){ - out[i] = (in[i] - in[i-1]) % modulus; - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h deleted file mode 100644 index c4ebbc4765..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_DIFF_DECODER_BB_H -#define INCLUDED_GR_DIFF_DECODER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_diff_decoder_bb; -typedef boost::shared_ptr<gr_diff_decoder_bb> gr_diff_decoder_bb_sptr; - -GR_CORE_API gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); - -/*! - * \brief y[0] = (x[0] - x[-1]) % M - * \ingroup coding_blk - * - * Differential decoder - */ -class GR_CORE_API gr_diff_decoder_bb : public gr_sync_block -{ - friend GR_CORE_API gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); - gr_diff_decoder_bb(unsigned int modulus); - - unsigned int d_modulus; - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc deleted file mode 100644 index 98492c746e..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_diff_encoder_bb.h> -#include <gr_io_signature.h> - -gr_diff_encoder_bb_sptr -gr_make_diff_encoder_bb (unsigned int modulus) -{ - return gnuradio::get_initial_sptr(new gr_diff_encoder_bb(modulus)); -} - -gr_diff_encoder_bb::gr_diff_encoder_bb (unsigned int modulus) - : gr_sync_block ("diff_encoder_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_last_out(0), d_modulus(modulus) -{ -} - -int -gr_diff_encoder_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - unsigned last_out = d_last_out; - unsigned modulus = d_modulus; - - for (int i = 0; i < noutput_items; i++){ - out[i] = (in[i] + last_out) % modulus; - last_out = out[i]; - } - - d_last_out = last_out; - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h deleted file mode 100644 index e98876b700..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_DIFF_ENCODER_BB_H -#define INCLUDED_GR_DIFF_ENCODER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_diff_encoder_bb; -typedef boost::shared_ptr<gr_diff_encoder_bb> gr_diff_encoder_bb_sptr; - -GR_CORE_API gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); - -/*! - * \brief y[0] = (x[0] + y[-1]) % M - * \ingroup coding_blk - * - * Differential encoder - */ -class GR_CORE_API gr_diff_encoder_bb : public gr_sync_block -{ - friend GR_CORE_API gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); - gr_diff_encoder_bb(unsigned int modulus); - - unsigned int d_last_out; - unsigned int d_modulus; - - public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc deleted file mode 100644 index 89fa2041e7..0000000000 --- a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_diff_phasor_cc.h> -#include <gr_io_signature.h> - -gr_diff_phasor_cc_sptr -gr_make_diff_phasor_cc () -{ - return gnuradio::get_initial_sptr(new gr_diff_phasor_cc()); -} - -gr_diff_phasor_cc::gr_diff_phasor_cc () - : gr_sync_block ("diff_phasor_cc", - gr_make_io_signature (1, 1, sizeof (gr_complex)), - gr_make_io_signature (1, 1, sizeof (gr_complex))) -{ - set_history(2); -} - - -gr_diff_phasor_cc::~gr_diff_phasor_cc(){} - -int -gr_diff_phasor_cc::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - gr_complex const *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - in += 1; // ensure that i - 1 is valid. - - for(int i = 0; i < noutput_items; i++){ - out[i] = in[i] * conj(in[i-1]); - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.cc b/gnuradio-core/src/lib/general/gr_float_to_char.cc index 3602ad7453..d67ded3ea6 100644 --- a/gnuradio-core/src/lib/general/gr_float_to_char.cc +++ b/gnuradio-core/src/lib/general/gr_float_to_char.cc @@ -42,7 +42,7 @@ gr_float_to_char::gr_float_to_char (size_t vlen, float scale) { const int alignment_multiple = volk_get_alignment() / sizeof(char); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } float diff --git a/gnuradio-core/src/lib/general/gr_float_to_int.cc b/gnuradio-core/src/lib/general/gr_float_to_int.cc index bd3cd6a3b3..43b8518956 100644 --- a/gnuradio-core/src/lib/general/gr_float_to_int.cc +++ b/gnuradio-core/src/lib/general/gr_float_to_int.cc @@ -43,7 +43,7 @@ gr_float_to_int::gr_float_to_int (size_t vlen, float scale) { const int alignment_multiple = volk_get_alignment() / sizeof(int); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } float diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.cc b/gnuradio-core/src/lib/general/gr_float_to_short.cc index 07995c99aa..ab720168bf 100644 --- a/gnuradio-core/src/lib/general/gr_float_to_short.cc +++ b/gnuradio-core/src/lib/general/gr_float_to_short.cc @@ -42,7 +42,7 @@ gr_float_to_short::gr_float_to_short (size_t vlen, float scale) { const int alignment_multiple = volk_get_alignment() / sizeof(short); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } float diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.cc b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc deleted file mode 100644 index 64a0af6a07..0000000000 --- a/gnuradio-core/src/lib/general/gr_framer_sink_1.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2006,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_framer_sink_1.h> -#include <gr_io_signature.h> -#include <cstdio> -#include <stdexcept> -#include <string.h> - -#define VERBOSE 0 - -inline void -gr_framer_sink_1::enter_search() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_search\n"); - - d_state = STATE_SYNC_SEARCH; -} - -inline void -gr_framer_sink_1::enter_have_sync() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_sync\n"); - - d_state = STATE_HAVE_SYNC; - d_header = 0; - d_headerbitlen_cnt = 0; -} - -inline void -gr_framer_sink_1::enter_have_header(int payload_len, int whitener_offset) -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", payload_len, whitener_offset); - - d_state = STATE_HAVE_HEADER; - d_packetlen = payload_len; - d_packet_whitener_offset = whitener_offset; - d_packetlen_cnt = 0; - d_packet_byte = 0; - d_packet_byte_index = 0; -} - -gr_framer_sink_1_sptr -gr_make_framer_sink_1(gr_msg_queue_sptr target_queue) -{ - return gnuradio::get_initial_sptr(new gr_framer_sink_1(target_queue)); -} - - -gr_framer_sink_1::gr_framer_sink_1(gr_msg_queue_sptr target_queue) - : gr_sync_block ("framer_sink_1", - gr_make_io_signature (1, 1, sizeof(unsigned char)), - gr_make_io_signature (0, 0, 0)), - d_target_queue(target_queue) -{ - enter_search(); -} - -gr_framer_sink_1::~gr_framer_sink_1 () -{ -} - -int -gr_framer_sink_1::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - int count=0; - - if (VERBOSE) - fprintf(stderr,">>> Entering state machine\n"); - - while (count < noutput_items){ - switch(d_state) { - - case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt - if (VERBOSE) - fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items); - - while (count < noutput_items) { - if (in[count] & 0x2){ // Found it, set up for header decode - enter_have_sync(); - break; - } - count++; - } - break; - - case STATE_HAVE_SYNC: - if (VERBOSE) - fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", - d_headerbitlen_cnt, d_header); - - while (count < noutput_items) { // Shift bits one at a time into header - d_header = (d_header << 1) | (in[count++] & 0x1); - if (++d_headerbitlen_cnt == HEADERBITLEN) { - - if (VERBOSE) - fprintf(stderr, "got header: 0x%08x\n", d_header); - - // we have a full header, check to see if it has been received properly - if (header_ok()){ - int payload_len; - int whitener_offset; - header_payload(&payload_len, &whitener_offset); - enter_have_header(payload_len, whitener_offset); - - if (d_packetlen == 0){ // check for zero-length payload - // build a zero-length message - // NOTE: passing header field as arg1 is not scalable - gr_message_sptr msg = - gr_make_message(0, d_packet_whitener_offset, 0, 0); - - d_target_queue->insert_tail(msg); // send it - msg.reset(); // free it up - - enter_search(); - } - } - else - enter_search(); // bad header - break; // we're in a new state - } - } - break; - - case STATE_HAVE_HEADER: - if (VERBOSE) - fprintf(stderr,"Packet Build\n"); - - while (count < noutput_items) { // shift bits into bytes of packet one at a time - d_packet_byte = (d_packet_byte << 1) | (in[count++] & 0x1); - if (d_packet_byte_index++ == 7) { // byte is full so move to next byte - d_packet[d_packetlen_cnt++] = d_packet_byte; - d_packet_byte_index = 0; - - if (d_packetlen_cnt == d_packetlen){ // packet is filled - - // build a message - // NOTE: passing header field as arg1 is not scalable - gr_message_sptr msg = - gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt); - memcpy(msg->msg(), d_packet, d_packetlen_cnt); - - d_target_queue->insert_tail(msg); // send it - msg.reset(); // free it up - - enter_search(); - break; - } - } - } - break; - - default: - assert(0); - - } // switch - - } // while - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.h b/gnuradio-core/src/lib/general/gr_framer_sink_1.h deleted file mode 100644 index 93e41745f3..0000000000 --- a/gnuradio-core/src/lib/general/gr_framer_sink_1.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_FRAMER_SINK_1_H -#define INCLUDED_GR_FRAMER_SINK_1_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include <gr_msg_queue.h> - -class gr_framer_sink_1; -typedef boost::shared_ptr<gr_framer_sink_1> gr_framer_sink_1_sptr; - -GR_CORE_API gr_framer_sink_1_sptr -gr_make_framer_sink_1 (gr_msg_queue_sptr target_queue); - -/*! - * \brief Given a stream of bits and access_code flags, assemble packets. - * \ingroup sink_blk - * - * input: stream of bytes from gr_correlate_access_code_bb - * output: none. Pushes assembled packet into target queue - * - * The framer expects a fixed length header of 2 16-bit shorts - * containing the payload length, followed by the payload. If the - * 2 16-bit shorts are not identical, this packet is ignored. Better - * algs are welcome. - * - * The input data consists of bytes that have two bits used. - * Bit 0, the LSB, contains the data bit. - * Bit 1 if set, indicates that the corresponding bit is the - * the first bit of the packet. That is, this bit is the first - * one after the access code. - */ -class GR_CORE_API gr_framer_sink_1 : public gr_sync_block -{ - friend GR_CORE_API gr_framer_sink_1_sptr - gr_make_framer_sink_1 (gr_msg_queue_sptr target_queue); - - private: - enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; - - static const int MAX_PKT_LEN = 4096; - static const int HEADERBITLEN = 32; - - gr_msg_queue_sptr d_target_queue; // where to send the packet when received - state_t d_state; - unsigned int d_header; // header bits - int d_headerbitlen_cnt; // how many so far - - unsigned char d_packet[MAX_PKT_LEN]; // assembled payload - unsigned char d_packet_byte; // byte being assembled - int d_packet_byte_index; // which bit of d_packet_byte we're working on - int d_packetlen; // length of packet - int d_packet_whitener_offset; // offset into whitener string to use - int d_packetlen_cnt; // how many so far - - protected: - gr_framer_sink_1(gr_msg_queue_sptr target_queue); - - void enter_search(); - void enter_have_sync(); - void enter_have_header(int payload_len, int whitener_offset); - - bool header_ok() - { - // confirm that two copies of header info are identical - return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; - } - - void header_payload(int *len, int *offset) - { - // header consists of two 16-bit shorts in network byte order - // payload length is lower 12 bits - // whitener offset is upper 4 bits - *len = (d_header >> 16) & 0x0fff; - *offset = (d_header >> 28) & 0x000f; - } - - public: - ~gr_framer_sink_1(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_FRAMER_SINK_1_H */ diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc b/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc deleted file mode 100644 index fcfeb80dcf..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_glfsr_source_b.h> -#include <gri_glfsr.h> -#include <gr_io_signature.h> -#include <stdexcept> - -gr_glfsr_source_b_sptr -gr_make_glfsr_source_b(int degree, bool repeat, int mask, int seed) -{ - return gnuradio::get_initial_sptr(new gr_glfsr_source_b(degree, repeat, mask, seed)); -} - -gr_glfsr_source_b::gr_glfsr_source_b(int degree, bool repeat, int mask, int seed) - : gr_sync_block ("glfsr_source_b", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (1, 1, sizeof(unsigned char))), - d_repeat(repeat), - d_index(0) -{ - if (degree < 1 || degree > 32) - throw std::runtime_error("gr_glfsr_source_b: degree must be between 1 and 32 inclusive"); - d_length = (unsigned int)((1ULL << degree)-1); - - if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); -} - -gr_glfsr_source_b::~gr_glfsr_source_b() -{ - delete d_glfsr; -} - -int -gr_glfsr_source_b::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - char *out = (char *) output_items[0]; - if ((d_index > d_length) && d_repeat == false) - return -1; /* once through the sequence */ - - int i; - for (i = 0; i < noutput_items; i++) { - out[i] = d_glfsr->next_bit(); - d_index++; - if (d_index > d_length && d_repeat == false) - break; - } - - return i; -} - -int -gr_glfsr_source_b::mask() const -{ - return d_glfsr->mask(); -} diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.h b/gnuradio-core/src/lib/general/gr_glfsr_source_b.h deleted file mode 100644 index 7549a76b32..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_b.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_GLFSR_SOURCE_B_H -#define INCLUDED_GR_GLFSR_SOURCE_B_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gri_glfsr; - -class gr_glfsr_source_b; -typedef boost::shared_ptr<gr_glfsr_source_b> gr_glfsr_source_b_sptr; - -GR_CORE_API gr_glfsr_source_b_sptr gr_make_glfsr_source_b(int degree, bool repeat=true, int mask=0, int seed=1); - -/*! - * \brief Galois LFSR pseudo-random source - * \ingroup source_blk - */ -class GR_CORE_API gr_glfsr_source_b : public gr_sync_block -{ - private: - friend GR_CORE_API gr_glfsr_source_b_sptr - gr_make_glfsr_source_b(int degree, bool repeat, int mask, int seed); - - gri_glfsr *d_glfsr; - - bool d_repeat; - unsigned int d_index; - unsigned int d_length; - - gr_glfsr_source_b(int degree, bool repeat, int mask, int seed); - - public: - - ~gr_glfsr_source_b(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - unsigned int period() const { return d_length; } - int mask() const; -}; - -#endif /* INCLUDED_GR_GLFSR_SOURCE_B_H */ diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.i b/gnuradio-core/src/lib/general/gr_glfsr_source_b.i deleted file mode 100644 index ffdd52ddba..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_b.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,glfsr_source_b); - -gr_glfsr_source_b_sptr -gr_make_glfsr_source_b(int degree, bool repeat=true, int mask=0, int seed=1) - throw (std::runtime_error); - -class gr_glfsr_source_b : public gr_sync_block -{ -protected: - gr_glfsr_source_b(int degree, bool repeat, int mask, int seed); - -public: - unsigned int period() const; - int mask() const; -}; diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc b/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc deleted file mode 100644 index a9efc8a706..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_glfsr_source_f.h> -#include <gri_glfsr.h> -#include <gr_io_signature.h> -#include <stdexcept> - -gr_glfsr_source_f_sptr -gr_make_glfsr_source_f(int degree, bool repeat, int mask, int seed) -{ - return gnuradio::get_initial_sptr(new gr_glfsr_source_f(degree, repeat, mask, seed)); -} - -gr_glfsr_source_f::gr_glfsr_source_f(int degree, bool repeat, int mask, int seed) - : gr_sync_block ("glfsr_source_f", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (1, 1, sizeof(float))), - d_repeat(repeat), - d_index(0) -{ - if (degree < 1 || degree > 32) - throw std::runtime_error("gr_glfsr_source_f: degree must be between 1 and 32 inclusive"); - d_length = (unsigned int)((1ULL << degree)-1); - - if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); -} - -gr_glfsr_source_f::~gr_glfsr_source_f() -{ - delete d_glfsr; -} - -int -gr_glfsr_source_f::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - float *out = (float *) output_items[0]; - if ((d_index > d_length) && d_repeat == false) - return -1; /* once through the sequence */ - - int i; - for (i = 0; i < noutput_items; i++) { - out[i] = (float)d_glfsr->next_bit()*2.0-1.0; - d_index++; - if (d_index > d_length && d_repeat == false) - break; - } - - return i; -} - -int -gr_glfsr_source_f::mask() const -{ - return d_glfsr->mask(); -} diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_f.h b/gnuradio-core/src/lib/general/gr_glfsr_source_f.h deleted file mode 100644 index 3549e3e5df..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_f.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_GLFSR_SOURCE_F_H -#define INCLUDED_GR_GLFSR_SOURCE_F_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gri_glfsr; - -class gr_glfsr_source_f; -typedef boost::shared_ptr<gr_glfsr_source_f> gr_glfsr_source_f_sptr; - -GR_CORE_API gr_glfsr_source_f_sptr gr_make_glfsr_source_f(int degree, bool repeat=true, int mask=0, int seed=1); - -/*! - * \brief Galois LFSR pseudo-random source generating float outputs -1.0 - 1.0 - * \ingroup source_blk - */ -class GR_CORE_API gr_glfsr_source_f : public gr_sync_block -{ - private: - friend GR_CORE_API gr_glfsr_source_f_sptr - gr_make_glfsr_source_f(int degree, bool repeat, int mask, int seed); - - gri_glfsr *d_glfsr; - - bool d_repeat; - unsigned int d_index; - unsigned int d_length; - - gr_glfsr_source_f(int degree, bool repeat, int mask, int seed); - - public: - - ~gr_glfsr_source_f(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - unsigned int period() const { return d_length; } - int mask() const; -}; - -#endif /* INCLUDED_GR_GLFSR_SOURCE_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_f.i b/gnuradio-core/src/lib/general/gr_glfsr_source_f.i deleted file mode 100644 index 2f84387c27..0000000000 --- a/gnuradio-core/src/lib/general/gr_glfsr_source_f.i +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,glfsr_source_f); - -gr_glfsr_source_f_sptr -gr_make_glfsr_source_f(int degree, bool repeat=true, int mask=0, int seed=1) - throw (std::runtime_error); - -class gr_glfsr_source_f : public gr_sync_block -{ -protected: - gr_glfsr_source_f(int degree, bool repeat, int mask, int seed); - -public: - unsigned int period() const; - int mask() const; -}; diff --git a/gnuradio-core/src/lib/general/gr_head.h b/gnuradio-core/src/lib/general/gr_head.h index 17dd737f0b..48415892dd 100644 --- a/gnuradio-core/src/lib/general/gr_head.h +++ b/gnuradio-core/src/lib/general/gr_head.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2009 Free Software Foundation, Inc. + * Copyright 2004,2009,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -51,6 +51,7 @@ class GR_CORE_API gr_head : public gr_sync_block gr_vector_void_star &output_items); void reset() { d_ncopied_items = 0; } + void set_length(int nitems) { d_nitems = nitems; } }; GR_CORE_API gr_head_sptr diff --git a/gnuradio-core/src/lib/general/gr_head.i b/gnuradio-core/src/lib/general/gr_head.i index 73feaf181c..11f3331d47 100644 --- a/gnuradio-core/src/lib/general/gr_head.i +++ b/gnuradio-core/src/lib/general/gr_head.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2009 Free Software Foundation, Inc. + * Copyright 2004,2009,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -28,5 +28,6 @@ class gr_head : public gr_block { gr_head(); public: void reset(); + void set_length(int nitems); }; diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.cc b/gnuradio-core/src/lib/general/gr_int_to_float.cc index a284853055..a7fb24dc69 100644 --- a/gnuradio-core/src/lib/general/gr_int_to_float.cc +++ b/gnuradio-core/src/lib/general/gr_int_to_float.cc @@ -42,7 +42,7 @@ gr_int_to_float::gr_int_to_float (size_t vlen, float scale) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_keep_m_in_n.cc b/gnuradio-core/src/lib/general/gr_keep_m_in_n.cc new file mode 100644 index 0000000000..1becbfa116 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_m_in_n.cc @@ -0,0 +1,98 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_keep_m_in_n.h> +#include <gr_io_signature.h> +#include <string.h> +#include <stdio.h> + +gr_keep_m_in_n_sptr +gr_make_keep_m_in_n(size_t item_size, int m, int n, int offset) +{ + return gnuradio::get_initial_sptr(new gr_keep_m_in_n(item_size, m, n, offset)); +} + + +/* +* +* offset = 0, starts with 0th item +* offset = 1, starts with 1st item, etc... +* +* we take m items out of each n +*/ +gr_keep_m_in_n::gr_keep_m_in_n(size_t item_size, int m, int n, int offset) + : gr_block("keep_m_in_n", + gr_make_io_signature(1, 1, item_size), + gr_make_io_signature(1, 1, item_size)), + d_n(n), + d_m(m), + d_offset(offset), + d_itemsize(item_size) +{ + // sanity checking + assert(d_m > 0); + assert(d_n > 0); + assert(d_m <= d_n); + assert(d_offset <= (d_n-d_m)); + + set_output_multiple(m); +} + + +void +gr_keep_m_in_n::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = d_n*(noutput_items/d_m); +} + +void +gr_keep_m_in_n::set_offset(int offset) +{ + d_offset = offset; +} + +int +gr_keep_m_in_n::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + uint8_t* out = (uint8_t*)output_items[0]; + const uint8_t* in = (const uint8_t*)input_items[0]; + + // iterate over data blocks of size {n, input : m, output} + int blks = std::min(noutput_items/d_m, ninput_items[0]/d_n); + for(int i=0; i<blks; i++) { + // set up copy pointers + const uint8_t* iptr = &in[(i*d_n + d_offset)*d_itemsize]; + uint8_t* optr = &out[i*d_m*d_itemsize]; + // perform copy + memcpy( optr, iptr, d_m*d_itemsize ); + } + + consume_each(d_n); + return d_m; +} diff --git a/gnuradio-core/src/lib/general/gr_keep_m_in_n.h b/gnuradio-core/src/lib/general/gr_keep_m_in_n.h new file mode 100644 index 0000000000..c6bf40ecf2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_m_in_n.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_KEEP_M_IN_N_H +#define INCLUDED_GR_KEEP_M_IN_N_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_keep_m_in_n; +typedef boost::shared_ptr<gr_keep_m_in_n> gr_keep_m_in_n_sptr; + +GR_CORE_API gr_keep_m_in_n_sptr +gr_make_keep_m_in_n (size_t item_size, int m, int n, int offset); + + +/*! + * \brief decimate a stream, keeping one item out of every n. + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_keep_m_in_n : public gr_block +{ + friend GR_CORE_API gr_keep_m_in_n_sptr + gr_make_keep_m_in_n (size_t item_size, int m, int n, int offset); + + int d_n; + int d_m; + int d_count; + int d_offset; + int d_itemsize; + + protected: + gr_keep_m_in_n (size_t item_size, int m, int n, int offset); + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + public: + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_offset(int offset); + void set_n(int n){ d_n = n; } + void set_m(int m){ d_m = m; } + +}; + +#endif /* INCLUDED_GR_KEEP_M_IN_N_H */ diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.i b/gnuradio-core/src/lib/general/gr_keep_m_in_n.i index 06281b138d..f280c0248a 100644 --- a/gnuradio-core/src/lib/general/gr_framer_sink_1.i +++ b/gnuradio-core/src/lib/general/gr_keep_m_in_n.i @@ -1,35 +1,35 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2006 Free Software Foundation, Inc. - * + * Copyright 2012 Free Software Foundation, Inc. + * * This file is part of GNU Radio - * + * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. - * + * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,framer_sink_1); +GR_SWIG_BLOCK_MAGIC(gr,keep_m_in_n) -gr_framer_sink_1_sptr -gr_make_framer_sink_1(gr_msg_queue_sptr target_queue); +gr_keep_m_in_n_sptr +gr_make_keep_m_in_n (size_t itemsize, int m, int n, int offset); -class gr_framer_sink_1 : public gr_sync_block +class gr_keep_m_in_n : public gr_sync_block { protected: - gr_framer_sink_1(gr_msg_queue_sptr target_queue); - + gr_keep_m_in_n (size_t itemsize, int m, int n, int offset); public: - ~gr_framer_sink_1(); + void set_offset(int offset); + }; diff --git a/gnuradio-core/src/lib/general/gr_map_bb.cc b/gnuradio-core/src/lib/general/gr_map_bb.cc deleted file mode 100644 index 7deb8971a5..0000000000 --- a/gnuradio-core/src/lib/general/gr_map_bb.cc +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_map_bb.h> -#include <gr_io_signature.h> - -gr_map_bb_sptr -gr_make_map_bb (const std::vector<int> &map) -{ - return gnuradio::get_initial_sptr(new gr_map_bb (map)); -} - -gr_map_bb::gr_map_bb (const std::vector<int> &map) - : gr_sync_block ("map_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))) -{ - for (int i = 0; i < 0x100; i++) - d_map[i] = i; - - unsigned int size = std::min((size_t) 0x100, map.size()); - for (unsigned int i = 0; i < size; i++) - d_map[i] = map[i]; -} - -int -gr_map_bb::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) - out[i] = d_map[in[i]]; - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_multiply_cc.cc b/gnuradio-core/src/lib/general/gr_multiply_cc.cc index 32c44a19e4..4a3751419f 100644 --- a/gnuradio-core/src/lib/general/gr_multiply_cc.cc +++ b/gnuradio-core/src/lib/general/gr_multiply_cc.cc @@ -40,9 +40,9 @@ gr_multiply_cc::gr_multiply_cc (size_t vlen) gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen)), d_vlen(vlen) { - const int alignment_multiple = - volk_get_alignment() / sizeof(gr_complex); - set_alignment(alignment_multiple); + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc index 53ede2eeda..0c5fb4a926 100644 --- a/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc +++ b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc @@ -40,9 +40,9 @@ gr_multiply_conjugate_cc::gr_multiply_conjugate_cc (size_t vlen) gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen)), d_vlen(vlen) { - const int alignment_multiple = - volk_get_alignment() / sizeof(gr_complex); - set_alignment(alignment_multiple); + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc b/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc index 359ab6ba05..bd4511937f 100644 --- a/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc +++ b/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc @@ -40,9 +40,9 @@ gr_multiply_const_cc::gr_multiply_const_cc (gr_complex k, size_t vlen) gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen)), d_k(k), d_vlen(vlen) { - const int alignment_multiple = - volk_get_alignment() / sizeof(gr_complex); - set_alignment(alignment_multiple); + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); } gr_complex diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc b/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc index 263f066106..16ba39df93 100644 --- a/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc +++ b/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc @@ -40,9 +40,9 @@ gr_multiply_const_ff::gr_multiply_const_ff (float k, size_t vlen) gr_make_io_signature (1, 1, sizeof (float)*vlen)), d_k(k), d_vlen(vlen) { - const int alignment_multiple = - volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); } float diff --git a/gnuradio-core/src/lib/general/gr_multiply_ff.cc b/gnuradio-core/src/lib/general/gr_multiply_ff.cc index f764a71e8f..bb7bd07550 100644 --- a/gnuradio-core/src/lib/general/gr_multiply_ff.cc +++ b/gnuradio-core/src/lib/general/gr_multiply_ff.cc @@ -42,7 +42,7 @@ gr_multiply_ff::gr_multiply_ff (size_t vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.cc b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.cc new file mode 100644 index 0000000000..0ea0c9e388 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pack_k_bits_bb.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb(unsigned k) +{ + return gnuradio::get_initial_sptr(new gr_pack_k_bits_bb(k)); +} + + +gr_pack_k_bits_bb::gr_pack_k_bits_bb (unsigned k) + : gr_sync_decimator("pack_k_bits_bb", + gr_make_io_signature (1, 1, sizeof(unsigned char)), + gr_make_io_signature (1, 1, sizeof(unsigned char)), + k), + d_k (k) +{ + if (d_k == 0) + throw std::out_of_range("interpolation must be > 0"); +} + +gr_pack_k_bits_bb::~gr_pack_k_bits_bb() +{ +} + +int +gr_pack_k_bits_bb::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *)input_items[0]; + unsigned char *out = (unsigned char *)output_items[0]; + + for(int i = 0; i < noutput_items; i++) { + out[i] = 0x00; + for(unsigned int j = 0; j < d_k; j++) { + out[i] |= (0x01 & in[i*d_k+j])<<(d_k-j-1); + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.h index 21c4f616d5..8e1508c78b 100644 --- a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h +++ b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.h @@ -1,49 +1,52 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. - * + * Copyright 2012 Free Software Foundation, Inc. + * * This file is part of GNU Radio - * + * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. - * + * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_DIFF_PHASOR_CC_H -#define INCLUDED_GR_DIFF_PHASOR_CC_H +#ifndef INCLUDED_GR_PACK_K_BITS_BB_H +#define INCLUDED_GR_PACK_K_BITS_BB_H #include <gr_core_api.h> -#include <gr_sync_block.h> +#include <gr_sync_decimator.h> -/*! - * \brief Please fix my documentation! - * \ingroup misc - */ -class gr_diff_phasor_cc; -typedef boost::shared_ptr<gr_diff_phasor_cc> gr_diff_phasor_cc_sptr; - -GR_CORE_API gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); +class gr_pack_k_bits_bb; +typedef boost::shared_ptr<gr_pack_k_bits_bb> gr_pack_k_bits_bb_sptr; +GR_CORE_API gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb (unsigned k); +class gr_pack_k_bits_bb; -class GR_CORE_API gr_diff_phasor_cc : public gr_sync_block +/*! + * \brief Converts a stream of bytes with 1 bit in the LSB to a byte with k relevent bits. + * \ingroup converter_blk + */ +class GR_CORE_API gr_pack_k_bits_bb : public gr_sync_decimator { - friend GR_CORE_API gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); + private: + friend GR_CORE_API gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb (unsigned k); - gr_diff_phasor_cc (); //constructor + gr_pack_k_bits_bb (unsigned k); + unsigned d_k; // number of relevent bits to pack from k input bytes + public: - ~gr_diff_phasor_cc(); //destructor + ~gr_pack_k_bits_bb (); int work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.i index 8aecd5cc77..6ae2095ec7 100644 --- a/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i +++ b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.i @@ -1,34 +1,34 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. - * + * Copyright 2012 Free Software Foundation, Inc. + * * This file is part of GNU Radio - * + * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. - * + * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,diff_phasor_cc) +GR_SWIG_BLOCK_MAGIC(gr,pack_k_bits_bb) -gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); +gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb (int k) throw(std::exception); -class gr_diff_phasor_cc : public gr_sync_block +class gr_pack_k_bits_bb : public gr_sync_decimator { private: - gr_diff_phasor_cc (); + gr_pack_k_bits_bb (int k); public: - ~gr_diff_phasor_cc(); + ~gr_pack_k_bits_bb (); }; diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.cc b/gnuradio-core/src/lib/general/gr_packet_sink.cc deleted file mode 100644 index 19a8c5fc20..0000000000 --- a/gnuradio-core/src/lib/general/gr_packet_sink.cc +++ /dev/null @@ -1,207 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_packet_sink.h> -#include <gr_io_signature.h> -#include <cstdio> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdexcept> -#include <gr_count_bits.h> -#include <string.h> - -#define VERBOSE 0 - -static const int DEFAULT_THRESHOLD = 12; // detect access code with up to DEFAULT_THRESHOLD bits wrong - -inline void -gr_packet_sink::enter_search() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_search\n"); - - d_state = STATE_SYNC_SEARCH; - d_shift_reg = 0; -} - -inline void -gr_packet_sink::enter_have_sync() -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_sync\n"); - - d_state = STATE_HAVE_SYNC; - d_header = 0; - d_headerbitlen_cnt = 0; -} - -inline void -gr_packet_sink::enter_have_header(int payload_len) -{ - if (VERBOSE) - fprintf(stderr, "@ enter_have_header (payload_len = %d)\n", payload_len); - - d_state = STATE_HAVE_HEADER; - d_packetlen = payload_len; - d_packetlen_cnt = 0; - d_packet_byte = 0; - d_packet_byte_index = 0; -} - -gr_packet_sink_sptr -gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, int threshold) -{ - return gnuradio::get_initial_sptr(new gr_packet_sink (sync_vector, target_queue, threshold)); -} - - -gr_packet_sink::gr_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, int threshold) - : gr_sync_block ("packet_sink", - gr_make_io_signature (1, 1, sizeof(float)), - gr_make_io_signature (0, 0, 0)), - d_target_queue(target_queue), d_threshold(threshold == -1 ? DEFAULT_THRESHOLD : threshold) -{ - d_sync_vector = 0; - for(int i=0;i<8;i++){ - d_sync_vector <<= 8; - d_sync_vector |= sync_vector[i]; - } - - enter_search(); -} - -gr_packet_sink::~gr_packet_sink () -{ -} - -int -gr_packet_sink::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - float *inbuf = (float *) input_items[0]; - int count=0; - - if (VERBOSE) - fprintf(stderr,">>> Entering state machine\n"),fflush(stderr); - - while (count<noutput_items) { - switch(d_state) { - - case STATE_SYNC_SEARCH: // Look for sync vector - if (VERBOSE) - fprintf(stderr,"SYNC Search, noutput=%d\n",noutput_items),fflush(stderr); - - while (count < noutput_items) { - if(slice(inbuf[count++])) - d_shift_reg = (d_shift_reg << 1) | 1; - else - d_shift_reg = d_shift_reg << 1; - - // Compute popcnt of putative sync vector - if(gr_count_bits64 (d_shift_reg ^ d_sync_vector) <= d_threshold) { - // Found it, set up for header decode - enter_have_sync(); - break; - } - } - break; - - case STATE_HAVE_SYNC: - if (VERBOSE) - fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", d_headerbitlen_cnt, d_header), - fflush(stderr); - - while (count < noutput_items) { // Shift bits one at a time into header - if(slice(inbuf[count++])) - d_header = (d_header << 1) | 1; - else - d_header = d_header << 1; - - if (++d_headerbitlen_cnt == HEADERBITLEN) { - - if (VERBOSE) - fprintf(stderr, "got header: 0x%08x\n", d_header); - - // we have a full header, check to see if it has been received properly - if (header_ok()){ - int payload_len = header_payload_len(); - if (payload_len <= MAX_PKT_LEN) // reasonable? - enter_have_header(payload_len); // yes. - else - enter_search(); // no. - } - else - enter_search(); // no. - break; // we're in a new state - } - } - break; - - case STATE_HAVE_HEADER: - if (VERBOSE) - fprintf(stderr,"Packet Build\n"),fflush(stderr); - - while (count < noutput_items) { // shift bits into bytes of packet one at a time - if(slice(inbuf[count++])) - d_packet_byte = (d_packet_byte << 1) | 1; - else - d_packet_byte = d_packet_byte << 1; - - if (d_packet_byte_index++ == 7) { // byte is full so move to next byte - d_packet[d_packetlen_cnt++] = d_packet_byte; - d_packet_byte_index = 0; - - if (d_packetlen_cnt == d_packetlen){ // packet is filled - - // build a message - gr_message_sptr msg = gr_make_message(0, 0, 0, d_packetlen_cnt); - memcpy(msg->msg(), d_packet, d_packetlen_cnt); - - d_target_queue->insert_tail(msg); // send it - msg.reset(); // free it up - - enter_search(); - break; - } - } - } - break; - - default: - assert(0); - - } // switch - - } // while - - return noutput_items; -} - diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.h b/gnuradio-core/src/lib/general/gr_packet_sink.h deleted file mode 100644 index b4cb0b0f6e..0000000000 --- a/gnuradio-core/src/lib/general/gr_packet_sink.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_PACKET_SINK_H -#define INCLUDED_GR_PACKET_SINK_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include <gr_msg_queue.h> - -class gr_packet_sink; -typedef boost::shared_ptr<gr_packet_sink> gr_packet_sink_sptr; - -GR_CORE_API gr_packet_sink_sptr -gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold = -1 // -1 -> use default - ); -/*! - * \brief process received bits looking for packet sync, header, and process bits into packet - * \ingroup sink_blk - */ -class GR_CORE_API gr_packet_sink : public gr_sync_block -{ - friend GR_CORE_API gr_packet_sink_sptr - gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold); - - private: - enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; - - static const int MAX_PKT_LEN = 4096; - static const int HEADERBITLEN = 32; - - gr_msg_queue_sptr d_target_queue; // where to send the packet when received - unsigned long long d_sync_vector; // access code to locate start of packet - unsigned int d_threshold; // how many bits may be wrong in sync vector - - state_t d_state; - - unsigned long long d_shift_reg; // used to look for sync_vector - - unsigned int d_header; // header bits - int d_headerbitlen_cnt; // how many so far - - unsigned char d_packet[MAX_PKT_LEN]; // assembled payload - unsigned char d_packet_byte; // byte being assembled - int d_packet_byte_index; // which bit of d_packet_byte we're working on - int d_packetlen; // length of packet - int d_packetlen_cnt; // how many so far - - protected: - gr_packet_sink(const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold); - - void enter_search(); - void enter_have_sync(); - void enter_have_header(int payload_len); - - int slice(float x) { return x > 0 ? 1 : 0; } - - bool header_ok() - { - // confirm that two copies of header info are identical - return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; - } - - int header_payload_len() - { - // header consists of two 16-bit shorts in network byte order - int t = (d_header >> 16) & 0xffff; - return t; - } - - public: - ~gr_packet_sink(); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - - //! return true if we detect carrier - bool carrier_sensed() const - { - return d_state != STATE_SYNC_SEARCH; - } - -}; - -#endif /* INCLUDED_GR_PACKET_SINK_H */ diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc deleted file mode 100644 index 818e48c34b..0000000000 --- a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_pn_correlator_cc.h> -#include <gr_io_signature.h> - -gr_pn_correlator_cc_sptr -gr_make_pn_correlator_cc(int degree, int mask, int seed) -{ - return gnuradio::get_initial_sptr(new gr_pn_correlator_cc(degree, mask, seed)); -} - -gr_pn_correlator_cc::gr_pn_correlator_cc(int degree, int mask, int seed) - : gr_sync_decimator ("pn_correlator_cc", - gr_make_io_signature (1, 1, sizeof(gr_complex)), - gr_make_io_signature (1, 1, sizeof(gr_complex)), - (unsigned int)((1ULL << degree)-1)) // PN code length -{ - d_len = (unsigned int)((1ULL << degree)-1); - if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_reference = new gri_glfsr(mask, seed); - for (int i = 0; i < d_len; i++) // initialize to last value in sequence - d_pn = 2.0*d_reference->next_bit()-1.0; -} - -gr_pn_correlator_cc::~gr_pn_correlator_cc() -{ - delete d_reference; -} - -int -gr_pn_correlator_cc::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const gr_complex *in = (const gr_complex *) input_items[0]; - gr_complex *out = (gr_complex *) output_items[0]; - gr_complex sum; - - for (int i = 0; i < noutput_items; i++) { - sum = 0.0; - - for (int j = 0; j < d_len; j++) { - if (j != 0) // retard PN generator one sample per period - d_pn = 2.0*d_reference->next_bit()-1.0; // no conditionals - sum += *in++ * d_pn; - } - - *out++ = sum*gr_complex(1.0/d_len, 0.0); - } - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h deleted file mode 100644 index 69bd2c502f..0000000000 --- a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_PN_CORRELATOR_CC_H -#define INCLUDED_GR_PN_CORRELATOR_CC_H - -#include <gr_core_api.h> -#include <gr_sync_decimator.h> -#include <gri_glfsr.h> - -class gr_pn_correlator_cc; -typedef boost::shared_ptr<gr_pn_correlator_cc> gr_pn_correlator_cc_sptr; - -GR_CORE_API gr_pn_correlator_cc_sptr -gr_make_pn_correlator_cc(int degree, int mask=0, int seed=1); -/*! - * \brief PN code sequential search correlator - * - * \ingroup sync_blk - * Receives complex baseband signal, outputs complex correlation against - * reference PN code, one sample per PN code period - */ - -class GR_CORE_API gr_pn_correlator_cc : public gr_sync_decimator -{ - friend GR_CORE_API gr_pn_correlator_cc_sptr gr_make_pn_correlator_cc(int degree, int mask, int seed); - - int d_len; - float d_pn; - gri_glfsr *d_reference; - - protected: - gr_pn_correlator_cc(int degree, int mask, int seed); - - public: - virtual int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - ~gr_pn_correlator_cc(); -}; - -#endif /* INCLUDED_GR_PN_CORRELATOR_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i deleted file mode 100644 index e992f33a7f..0000000000 --- a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,pn_correlator_cc) - -gr_pn_correlator_cc_sptr -gr_make_pn_correlator_cc(int degree, int mask=0, int seed=1); - -class gr_pn_correlator_cc : public gr_sync_decimator -{ - protected: - gr_pn_correlator_cc(); -}; diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.cc b/gnuradio-core/src/lib/general/gr_probe_density_b.cc deleted file mode 100644 index 31661780af..0000000000 --- a/gnuradio-core/src/lib/general/gr_probe_density_b.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_probe_density_b.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <iostream> - -gr_probe_density_b_sptr -gr_make_probe_density_b(double alpha) -{ - return gnuradio::get_initial_sptr(new gr_probe_density_b(alpha)); -} - -gr_probe_density_b::gr_probe_density_b(double alpha) - : gr_sync_block("density_b", - gr_make_io_signature(1, 1, sizeof(char)), - gr_make_io_signature(0, 0, 0)) -{ - set_alpha(alpha); - d_density = 1.0; -} - -gr_probe_density_b::~gr_probe_density_b() -{ -} - -int -gr_probe_density_b::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const char *in = (const char *)input_items[0]; - - for (int i = 0; i < noutput_items; i++) - d_density = d_alpha*(double)in[i] + d_beta*d_density; - - return noutput_items; -} - -void -gr_probe_density_b::set_alpha(double alpha) -{ - d_alpha = alpha; - d_beta = 1.0-d_alpha; -} - diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.h b/gnuradio-core/src/lib/general/gr_probe_density_b.h deleted file mode 100644 index ab84a63a96..0000000000 --- a/gnuradio-core/src/lib/general/gr_probe_density_b.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_PROBE_DENSITY_B_H -#define INCLUDED_GR_PROBE_DENSITY_B_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_probe_density_b; - -typedef boost::shared_ptr<gr_probe_density_b> gr_probe_density_b_sptr; - -GR_CORE_API gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); - -/*! - * This block maintains a running average of the input stream and - * makes it available as an accessor function. The input stream - * is type unsigned char. - * - * If you send this block a stream of unpacked bytes, it will tell - * you what the bit density is. - * - * \param alpha Average filter constant - * - */ - -class GR_CORE_API gr_probe_density_b : public gr_sync_block -{ -private: - friend GR_CORE_API gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); - - double d_alpha; - double d_beta; - double d_density; - - gr_probe_density_b(double alpha); - -public: - ~gr_probe_density_b(); - - /*! - * \brief Returns the current density value - */ - double density() const { return d_density; } - - /*! - * \brief Set the average filter constant - */ - void set_alpha(double alpha); - - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_PROBE_DENSITY_B_H */ diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.cc b/gnuradio-core/src/lib/general/gr_scrambler_bb.cc deleted file mode 100644 index 31eb192077..0000000000 --- a/gnuradio-core/src/lib/general/gr_scrambler_bb.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_scrambler_bb.h> -#include <gr_io_signature.h> - -gr_scrambler_bb_sptr -gr_make_scrambler_bb(int mask, int seed, int len) -{ - return gnuradio::get_initial_sptr(new gr_scrambler_bb(mask, seed, len)); -} - -gr_scrambler_bb::gr_scrambler_bb(int mask, int seed, int len) - : gr_sync_block("scrambler_bb", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_lfsr(mask, seed, len) -{ -} - -int -gr_scrambler_bb::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - for (int i = 0; i < noutput_items; i++) - out[i] = d_lfsr.next_bit_scramble(in[i]); - - return noutput_items; -} diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.h b/gnuradio-core/src/lib/general/gr_scrambler_bb.h deleted file mode 100644 index edb429e0a0..0000000000 --- a/gnuradio-core/src/lib/general/gr_scrambler_bb.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_SCRAMBLER_BB_H -#define INCLUDED_GR_SCRAMBLER_BB_H - -#include <gr_core_api.h> -#include <gr_sync_block.h> -#include "gri_lfsr.h" - -class gr_scrambler_bb; -typedef boost::shared_ptr<gr_scrambler_bb> gr_scrambler_bb_sptr; - -GR_CORE_API gr_scrambler_bb_sptr gr_make_scrambler_bb(int mask, int seed, int len); - -/*! - * Scramble an input stream using an LFSR. This block works on the LSB only - * of the input data stream, i.e., on an "unpacked binary" stream, and - * produces the same format on its output. - * - * \param mask Polynomial mask for LFSR - * \param seed Initial shift register contents - * \param len Shift register length - * - * \ingroup coding_blk - */ - -class GR_CORE_API gr_scrambler_bb : public gr_sync_block -{ - friend GR_CORE_API gr_scrambler_bb_sptr gr_make_scrambler_bb(int mask, int seed, int len); - - gri_lfsr d_lfsr; - - gr_scrambler_bb(int mask, int seed, int len); - -public: - int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_SCRAMBLER_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.i b/gnuradio-core/src/lib/general/gr_scrambler_bb.i deleted file mode 100644 index a7ef7b364f..0000000000 --- a/gnuradio-core/src/lib/general/gr_scrambler_bb.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,scrambler_bb); - -gr_scrambler_bb_sptr gr_make_scrambler_bb(int mask, int seed, int len); - -class gr_scrambler_bb : public gr_sync_block -{ -private: - gr_scrambler_bb(int mask, int seed, int len); -}; diff --git a/gnuradio-core/src/lib/general/gr_short_to_char.cc b/gnuradio-core/src/lib/general/gr_short_to_char.cc index 9d6c41406e..8c146a351d 100644 --- a/gnuradio-core/src/lib/general/gr_short_to_char.cc +++ b/gnuradio-core/src/lib/general/gr_short_to_char.cc @@ -42,7 +42,7 @@ gr_short_to_char::gr_short_to_char (size_t vlen) { const int alignment_multiple = volk_get_alignment() / sizeof(char); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } int diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.cc b/gnuradio-core/src/lib/general/gr_short_to_float.cc index 960cf644d1..093d6024fa 100644 --- a/gnuradio-core/src/lib/general/gr_short_to_float.cc +++ b/gnuradio-core/src/lib/general/gr_short_to_float.cc @@ -42,7 +42,7 @@ gr_short_to_float::gr_short_to_float (size_t vlen, float scale) { const int alignment_multiple = volk_get_alignment() / sizeof(float); - set_alignment(alignment_multiple); + set_alignment(std::max(1,alignment_multiple)); } float diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.cc b/gnuradio-core/src/lib/general/gr_simple_framer.cc deleted file mode 100644 index 506603bb71..0000000000 --- a/gnuradio-core/src/lib/general/gr_simple_framer.cc +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_simple_framer.h> -#include <gr_simple_framer_sync.h> -#include <gr_io_signature.h> -#include <assert.h> -#include <stdexcept> -#include <string.h> - - -gr_simple_framer_sptr -gr_make_simple_framer (int payload_bytesize) -{ - return gnuradio::get_initial_sptr(new gr_simple_framer (payload_bytesize)); -} - -gr_simple_framer::gr_simple_framer (int payload_bytesize) - : gr_block ("simple_framer", - gr_make_io_signature (1, 1, sizeof (unsigned char)), - gr_make_io_signature (1, 1, sizeof (unsigned char))), - d_seqno (0), d_payload_bytesize (payload_bytesize), - d_input_block_size (payload_bytesize), - d_output_block_size (payload_bytesize + GRSF_OVERHEAD) -{ - set_output_multiple (d_output_block_size); -} - -void -gr_simple_framer::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - assert (noutput_items % d_output_block_size == 0); - - int nblocks = noutput_items / d_output_block_size; - int input_required = nblocks * d_input_block_size; - - unsigned ninputs = ninput_items_required.size(); - for (unsigned int i = 0; i < ninputs; i++) - ninput_items_required[i] = input_required; -} - -int -gr_simple_framer::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - const unsigned char *in = (const unsigned char *) input_items[0]; - unsigned char *out = (unsigned char *) output_items[0]; - - int n = 0; - int nblocks = 0; - - memset (out, 0x55, noutput_items); - - while (n < noutput_items){ - out[0] = (GRSF_SYNC >> 56) & 0xff; - out[1] = (GRSF_SYNC >> 48) & 0xff; - out[2] = (GRSF_SYNC >> 40) & 0xff; - out[3] = (GRSF_SYNC >> 32) & 0xff; - out[4] = (GRSF_SYNC >> 24) & 0xff; - out[5] = (GRSF_SYNC >> 16) & 0xff; - out[6] = (GRSF_SYNC >> 8) & 0xff; - out[7] = (GRSF_SYNC >> 0) & 0xff; - out[8] = d_seqno++; - - memcpy (&out[9], in, d_input_block_size); - in += d_input_block_size; - out += d_output_block_size; - n += d_output_block_size; - nblocks++; - } - - assert (n == noutput_items); - - consume_each (nblocks * d_input_block_size); - return n; -} diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.h b/gnuradio-core/src/lib/general/gr_simple_framer.h deleted file mode 100644 index 76a4b7baba..0000000000 --- a/gnuradio-core/src/lib/general/gr_simple_framer.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_SIMPLE_FRAMER_H -#define INCLUDED_GR_SIMPLE_FRAMER_H - -#include <gr_core_api.h> -#include <gr_block.h> - -class gr_simple_framer; -typedef boost::shared_ptr<gr_simple_framer> gr_simple_framer_sptr; - -GR_CORE_API gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); - -/*! - * \brief add sync field, seq number and command field to payload - * \ingroup sync_blk - */ -class GR_CORE_API gr_simple_framer : public gr_block -{ - int d_seqno; - int d_payload_bytesize; - int d_input_block_size; // bytes - int d_output_block_size; // bytes - - friend GR_CORE_API gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); - gr_simple_framer (int payload_bytesize); - - public: - void forecast (int noutput_items, - gr_vector_int &ninput_items_required); - - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - - -#endif /* INCLUDED_GR_SIMPLE_FRAMER_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.i b/gnuradio-core/src/lib/general/gr_simple_framer.i deleted file mode 100644 index c13ead87bf..0000000000 --- a/gnuradio-core/src/lib/general/gr_simple_framer.i +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -GR_SWIG_BLOCK_MAGIC(gr,simple_framer); - -gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); - -class gr_simple_framer : public gr_block -{ - private: - gr_simple_framer (int payload_bytesize); -}; diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.cc b/gnuradio-core/src/lib/general/gr_tag_debug.cc new file mode 100644 index 0000000000..c4031f438d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_tag_debug.cc @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_tag_debug.h> +#include <gr_io_signature.h> +#include <iostream> +#include <iomanip> + +gr_tag_debug_sptr +gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name) +{ + return gnuradio::get_initial_sptr + (new gr_tag_debug(sizeof_stream_item, name)); +} + +gr_tag_debug::gr_tag_debug(size_t sizeof_stream_item, const std::string &name) + : gr_sync_block("tag_debug", + gr_make_io_signature(1, -1, sizeof_stream_item), + gr_make_io_signature(0, 0, 0)), + d_name(name), d_display(true) +{ +} + +std::vector<gr_tag_t> +gr_tag_debug::current_tags() +{ + gruel::scoped_lock l(d_mutex); + return d_tags; +} + +void +gr_tag_debug::set_display(bool d) +{ + gruel::scoped_lock l(d_mutex); + d_display = d; +} + +int +gr_tag_debug::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock l(d_mutex); + + if(d_display) { + std::cout << std::endl + << "----------------------------------------------------------------------"; + std::cout << std::endl << "Tag Debug: " << d_name << std::endl; + } + + uint64_t abs_N, end_N; + for(size_t i = 0; i < input_items.size(); i++) { + abs_N = nitems_read(i); + end_N = abs_N + (uint64_t)(noutput_items); + + d_tags.clear(); + get_tags_in_range(d_tags, i, abs_N, end_N); + + if(d_display) { + std::cout << "Input Stream: " << i << std::endl; + for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) { + std::cout << std::setw(10) << "Offset: " << d_tags_itr->offset + << std::setw(10) << "Source: " << pmt::pmt_symbol_to_string(d_tags_itr->srcid) + << std::setw(10) << "Key: " << pmt::pmt_symbol_to_string(d_tags_itr->key) + << std::setw(10) << "Value: "; + pmt::pmt_print(d_tags_itr->value); + } + } + } + + if(d_display) { + std::cout << "----------------------------------------------------------------------"; + std::cout << std::endl; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.h b/gnuradio-core/src/lib/general/gr_tag_debug.h new file mode 100644 index 0000000000..57578884a8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_tag_debug.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TAG_DEBUG_H +#define INCLUDED_GR_TAG_DEBUG_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/thread.h> +#include <stddef.h> + +class gr_tag_debug; +typedef boost::shared_ptr<gr_tag_debug> gr_tag_debug_sptr; + +GR_CORE_API gr_tag_debug_sptr +gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name); + +/*! + * \brief Bit bucket that prints out any tag received. + * \ingroup sink_blk + * + * This block collects all tags sent to it on all input ports and + * displays them to stdout in a formatted way. The \p name parameter + * is used to identify which debug sink generated the tag, so when + * connecting a block to this debug sink, an appropriate name is + * something that identifies the input block. + * + * This block otherwise acts as a NULL sink in that items from the + * input stream are ignored. It is designed to be able to attach to + * any block and watch all tags streaming out of that block for + * debugging purposes. + * + * The tags from the last call to this work function are stored and + * can be retrieved using the function 'current_tags'. + */ +class GR_CORE_API gr_tag_debug : public gr_sync_block +{ + private: + friend GR_CORE_API gr_tag_debug_sptr + gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name); + gr_tag_debug(size_t sizeof_stream_item, const std::string &name); + + std::string d_name; + std::vector<gr_tag_t> d_tags; + std::vector<gr_tag_t>::iterator d_tags_itr; + bool d_display; + gruel::mutex d_mutex; + + public: + /*! + * \brief Returns a vector of gr_tag_t items as of the last call to + * work. + */ + std::vector<gr_tag_t> current_tags(); + + /*! + * \brief Set the display of tags to stdout on/off. + */ + void set_display(bool d); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_TAG_DEBUG_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.i b/gnuradio-core/src/lib/general/gr_tag_debug.i index ca65708af6..3af1bdcfef 100644 --- a/gnuradio-core/src/lib/general/gr_probe_density_b.i +++ b/gnuradio-core/src/lib/general/gr_tag_debug.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,17 +20,16 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,probe_density_b); +GR_SWIG_BLOCK_MAGIC(gr,tag_debug) -gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); +%include <gr_tags.i> -class gr_probe_density_b : public gr_sync_block +gr_tag_debug_sptr +gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name); + +class gr_tag_debug : public gr_sync_block { public: - double density() const; - - void set_alpha(double alpha); - -private: - gr_probe_density_b(); + std::vector<gr_tag_t> current_tags(); + void set_display(bool d); }; diff --git a/gnuradio-core/src/lib/general/gr_vector_map.cc b/gnuradio-core/src/lib/general/gr_vector_map.cc new file mode 100644 index 0000000000..2a13efb06d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_map.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_vector_map.h> +#include <gr_io_signature.h> +#include <string.h> + +std::vector<int> +get_in_sizeofs(size_t item_size, std::vector<size_t> in_vlens) +{ + std::vector<int> in_sizeofs; + for(unsigned int i = 0; i < in_vlens.size(); i++) { + in_sizeofs.push_back(in_vlens[i]*item_size); + } + return in_sizeofs; +} + +std::vector<int> +get_out_sizeofs(size_t item_size, + std::vector< std::vector< std::vector<size_t> > > mapping) +{ + std::vector<int> out_sizeofs; + for(unsigned int i = 0; i < mapping.size(); i++) { + out_sizeofs.push_back(mapping[i].size()*item_size); + } + return out_sizeofs; +} + +gr_vector_map_sptr +gr_make_vector_map (size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping) +{ + return gnuradio::get_initial_sptr(new gr_vector_map(item_size, + in_vlens, + mapping)); +} + +gr_vector_map::gr_vector_map(size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping) + : gr_sync_block("vector_map", + gr_make_io_signaturev(in_vlens.size(), in_vlens.size(), + get_in_sizeofs(item_size, in_vlens)), + gr_make_io_signaturev(mapping.size(), mapping.size(), + get_out_sizeofs(item_size, mapping))), + d_item_size(item_size), d_in_vlens(in_vlens) +{ + set_mapping(mapping); +} + +void +gr_vector_map::set_mapping(std::vector< std::vector< std::vector<size_t> > > mapping) { + // Make sure the contents of the mapping vectors are possible. + for(unsigned int i=0; i<mapping.size(); i++) { + for(unsigned int j=0; j<mapping[i].size(); j++) { + if(mapping[i][j].size() != 2) { + throw std::runtime_error("Mapping must be of the form (out_mapping_stream1, out_mapping_stream2, ...), where out_mapping_stream1 is of the form (mapping_element1, mapping_element2, ...), where mapping_element1 is of the form (input_stream, input_element). This error is raised because a mapping_element vector does not contain exactly 2 items."); + } + unsigned int s = mapping[i][j][0]; + unsigned int index = mapping[i][j][1]; + if(s >= d_in_vlens.size()) { + throw std::runtime_error("Stream numbers in mapping must be less than the number of input streams."); + } + if((index < 0) || (index >= d_in_vlens[s])) { + throw std::runtime_error ("Indices in mapping must be greater than 0 and less than the input vector lengths."); + } + } + } + gruel::scoped_lock guard(d_mutex); + d_mapping = mapping; +} + +int +gr_vector_map::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char **inv = (const char **) &input_items[0]; + char **outv = (char **) &output_items[0]; + + for(unsigned int n = 0; n < (unsigned int)(noutput_items); n++) { + for(unsigned int i = 0; i < d_mapping.size(); i++) { + unsigned int out_vlen = d_mapping[i].size(); + for(unsigned int j = 0; j < out_vlen; j++) { + unsigned int s = d_mapping[i][j][0]; + unsigned int k = d_mapping[i][j][1]; + memcpy(outv[i] + out_vlen*d_item_size*n + + d_item_size*j, inv[s] + d_in_vlens[s]*d_item_size*n + + k*d_item_size, d_item_size); + } + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_map.h b/gnuradio-core/src/lib/general/gr_vector_map.h new file mode 100644 index 0000000000..f5492b1e3a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_map.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_VECTOR_MAP_H +#define INCLUDED_GR_VECTOR_MAP_H + +#include <vector> +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> +#include <gruel/thread.h> + +class gr_vector_map; +typedef boost::shared_ptr<gr_vector_map> gr_vector_map_sptr; + +GR_CORE_API gr_vector_map_sptr +gr_make_vector_map (size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping); + +/*! + * \brief Maps elements from a set of input vectors to a set of output vectors. + * + * If in[i] is the input vector in the i'th stream then the output + * vector in the j'th stream is: + * + * out[j][k] = in[mapping[j][k][0]][mapping[j][k][1]] + * + * That is mapping is of the form (out_stream1_mapping, + * out_stream2_mapping, ...) and out_stream1_mapping is of the form + * (element1_mapping, element2_mapping, ...) and element1_mapping is + * of the form (in_stream, in_element). + * + * \param item_size (integer) size of vector elements + * + * \param in_vlens (vector of integers) number of elements in each + * input vector + * + * \param mapping (vector of vectors of vectors of integers) how to + * map elements from input to output vectors + * + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_vector_map : public gr_sync_block +{ + friend GR_CORE_API gr_vector_map_sptr + gr_make_vector_map(size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping); + size_t d_item_size; + std::vector<size_t> d_in_vlens; + std::vector< std::vector< std::vector<size_t> > > d_mapping; + gruel::mutex d_mutex; // mutex to protect set/work access + + protected: + gr_vector_map(size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping); + + public: + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_mapping(std::vector< std::vector< std::vector<size_t> > > mapping); +}; + +#endif /* INCLUDED_GR_VECTOR_MAP_H */ diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.i b/gnuradio-core/src/lib/general/gr_vector_map.i index 185e7cd290..e9fa3f27e5 100644 --- a/gnuradio-core/src/lib/general/gr_bytes_to_syms.i +++ b/gnuradio-core/src/lib/general/gr_vector_map.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,11 +20,9 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,bytes_to_syms); +GR_SWIG_BLOCK_MAGIC(gr, vector_map); -gr_bytes_to_syms_sptr gr_make_bytes_to_syms (); +%template() std::vector<size_t>; +%template() std::vector< std::vector< std::vector<size_t> > >; -class gr_bytes_to_syms : public gr_sync_interpolator -{ - gr_bytes_to_syms (); -}; +%include "gr_vector_map.h" diff --git a/gnuradio-core/src/lib/general/gri_glfsr.cc b/gnuradio-core/src/lib/general/gri_glfsr.cc deleted file mode 100644 index ba6951882b..0000000000 --- a/gnuradio-core/src/lib/general/gri_glfsr.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gri_glfsr.h> -#include <stdexcept> - -static int s_polynomial_masks[] = { - 0x00000000, - 0x00000001, // x^1 + 1 - 0x00000003, // x^2 + x^1 + 1 - 0x00000005, // x^3 + x^1 + 1 - 0x00000009, // x^4 + x^1 + 1 - 0x00000012, // x^5 + x^2 + 1 - 0x00000021, // x^6 + x^1 + 1 - 0x00000041, // x^7 + x^1 + 1 - 0x0000008E, // x^8 + x^4 + x^3 + x^2 + 1 - 0x00000108, // x^9 + x^4 + 1 - 0x00000204, // x^10 + x^4 + 1 - 0x00000402, // x^11 + x^2 + 1 - 0x00000829, // x^12 + x^6 + x^4 + x^1 + 1 - 0x0000100D, // x^13 + x^4 + x^3 + x^1 + 1 - 0x00002015, // x^14 + x^5 + x^3 + x^1 + 1 - 0x00004001, // x^15 + x^1 + 1 - 0x00008016, // x^16 + x^5 + x^3 + x^2 + 1 - 0x00010004, // x^17 + x^3 + 1 - 0x00020013, // x^18 + x^5 + x^2 + x^1 + 1 - 0x00040013, // x^19 + x^5 + x^2 + x^1 + 1 - 0x00080004, // x^20 + x^3 + 1 - 0x00100002, // x^21 + x^2 + 1 - 0x00200001, // x^22 + x^1 + 1 - 0x00400010, // x^23 + x^5 + 1 - 0x0080000D, // x^24 + x^4 + x^3 + x^1 + 1 - 0x01000004, // x^25 + x^3 + 1 - 0x02000023, // x^26 + x^6 + x^2 + x^1 + 1 - 0x04000013, // x^27 + x^5 + x^2 + x^1 + 1 - 0x08000004, // x^28 + x^3 + 1 - 0x10000002, // x^29 + x^2 + 1 - 0x20000029, // x^30 + x^4 + x^1 + 1 - 0x40000004, // x^31 + x^3 + 1 - 0x80000057 // x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + 1 -}; - -int gri_glfsr::glfsr_mask(int degree) -{ - if (degree < 1 || degree > 32) - throw std::runtime_error("gri_glfsr::glfsr_mask(): degree must be between 1 and 32 inclusive"); - return s_polynomial_masks[degree]; -} diff --git a/gnuradio-core/src/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc index 26b21983e6..61e5c159bd 100644 --- a/gnuradio-core/src/lib/general/qa_general.cc +++ b/gnuradio-core/src/lib/general/qa_general.cc @@ -33,7 +33,6 @@ #include <qa_gr_fxpt_nco.h> #include <qa_gr_fxpt_vco.h> #include <qa_gr_math.h> -#include <qa_gri_lfsr.h> CppUnit::TestSuite * qa_general::suite () @@ -47,7 +46,6 @@ qa_general::suite () s->addTest (qa_gr_fxpt_nco::suite ()); s->addTest (qa_gr_fxpt_vco::suite ()); s->addTest (qa_gr_math::suite ()); - s->addTest (qa_gri_lfsr::suite ()); return s; } diff --git a/gnuradio-core/src/lib/general/qa_gri_lfsr.cc b/gnuradio-core/src/lib/general/qa_gri_lfsr.cc deleted file mode 100644 index 87d610df68..0000000000 --- a/gnuradio-core/src/lib/general/qa_gri_lfsr.cc +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2008 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gri_lfsr.h> -#include <qa_gri_lfsr.h> -#include <cppunit/TestAssert.h> -#include <stdio.h> -#include <string.h> -#include <vector> - -void -qa_gri_lfsr::test_lfsr () -{ - int mask = 0x19; - int seed = 0x01; - int length = 5; - - gri_lfsr lfsr1(mask,seed,length); - gri_lfsr lfsr2(mask,seed,length); - - unsigned char expected[] = {1, 0, 1, 1, 0, 1, 0, 1, 0, 0}; - - for(unsigned int i=0; i<31; i++){ - lfsr1.next_bit(); - } - - // test that after one lfsr cycle we still match out uncycled lfsr - for (unsigned int i = 0; i < 41; i++) { - CPPUNIT_ASSERT_EQUAL((int) lfsr1.next_bit(), (int) lfsr2.next_bit()); - } - - // test the known correct values at the given shift offset - for(unsigned int i=0; i<10; i++){ - CPPUNIT_ASSERT_EQUAL((int) lfsr1.next_bit(), (int) expected[i]); - } - - // test for register length too long - CPPUNIT_ASSERT_THROW(gri_lfsr(mask, seed, 32), std::invalid_argument); -} - -void -qa_gri_lfsr::test_scrambler() -{ - // CCSDS 7-bit scrambler - int mask = 0x8A; - int seed = 0x7F; - int length = 7; - - gri_lfsr scrambler(mask, seed, length); - - // Impulse (1 and 126 more zeroes) - unsigned char src[] = - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0 }; // flush bits - - // Impulse response (including leading bits) - unsigned char expected[] = - { 1, 1, 1, 1, 1, 1, 1, - 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, - 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, - 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, - 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, }; - - int len = sizeof(src); - std::vector<unsigned char> actual(len); - - for (int i = 0; i < len; i++) - actual[i] = scrambler.next_bit_scramble(src[i]); - - CPPUNIT_ASSERT(memcmp(expected, &actual[0], len) == 0); -} - -void -qa_gri_lfsr::test_descrambler() -{ - // CCSDS 7-bit scrambler - int mask = 0x8A; - int seed = 0x7F; - int length = 7; - - gri_lfsr descrambler(mask, seed, length); - - // Scrambled sequence (impulse response) - unsigned char src[] = - { 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, - 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, - 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, - 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, - 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, - 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0 }; - - // Original (garbage while synchronizing, them impulse) - unsigned char expected[] = - { 0, 1, 0, 0, 1, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - int len = sizeof(src); - std::vector<unsigned char> actual(len); - - for (int i = 0; i < len; i++) - actual[i] = descrambler.next_bit_descramble(src[i]); - - CPPUNIT_ASSERT(memcmp(expected, &actual[0], len) == 0); -} diff --git a/gnuradio-core/src/lib/gengen/CMakeLists.txt b/gnuradio-core/src/lib/gengen/CMakeLists.txt index d137769907..ed49cf07e5 100644 --- a/gnuradio-core/src/lib/gengen/CMakeLists.txt +++ b/gnuradio-core/src/lib/gengen/CMakeLists.txt @@ -82,13 +82,14 @@ endmacro(expand_h_cc_i) # Invoke macro to generate various sources ######################################################################## expand_h_cc_i(gr_vector_source_X b s i f c) +expand_h_cc_i(gr_vector_insert_X b) expand_h_cc_i(gr_vector_sink_X b s i f c) expand_h_cc_i(gr_noise_source_X s i f c) expand_h_cc_i(gr_sig_source_X s i f c) expand_h_cc_i(gr_probe_signal_X b s i f c) expand_h_cc_i(gr_probe_signal_vX b s i f c) -expand_h_cc_i(gr_add_const_XX ss ii ff cc sf) +expand_h_cc_i(gr_add_const_XX bb ss ii ff cc sf) expand_h_cc_i(gr_multiply_const_XX ss ii) expand_h_cc_i(gr_add_XX ss ii cc) expand_h_cc_i(gr_sub_XX ss ii ff cc) @@ -100,7 +101,6 @@ expand_h_cc_i(gr_multiply_const_vXX ss ii ff cc) expand_h_cc_i(gr_integrate_XX ss ii ff cc) expand_h_cc_i(gr_moving_average_XX ss ii ff cc) -expand_h_cc_i(gr_chunks_to_symbols_XX bf bc sf sc if ic) expand_h_cc_i(gr_unpacked_to_packed_XX bb ss ii) expand_h_cc_i(gr_packed_to_unpacked_XX bb ss ii) expand_h_cc_i(gr_xor_XX bb ss ii) diff --git a/gnuradio-core/src/lib/gengen/generate_common.py b/gnuradio-core/src/lib/gengen/generate_common.py index 13d01b0f90..37d8944f5b 100755 --- a/gnuradio-core/src/lib/gengen/generate_common.py +++ b/gnuradio-core/src/lib/gengen/generate_common.py @@ -54,7 +54,6 @@ reg_roots = [ # other blocks others = ( - ('gr_chunks_to_symbols_XX', ('bf', 'bc', 'sf', 'sc', 'if', 'ic')), ('gr_unpacked_to_packed_XX', ('bb','ss','ii')), ('gr_packed_to_unpacked_XX', ('bb','ss','ii')), ('gr_xor_XX', ('bb','ss','ii')), diff --git a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t deleted file mode 100644 index 4a642c13e2..0000000000 --- a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2010 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -// @WARNING@ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <@NAME@.h> -#include <gr_io_signature.h> -#include <assert.h> -#include <iostream> -#include <string.h> - -@SPTR_NAME@ -gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) -{ - return gnuradio::get_initial_sptr (new @NAME@ (symbol_table,D)); -} - -@NAME@::@NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) - : gr_sync_interpolator ("@BASE_NAME@", - gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), - gr_make_io_signature (1, -1, sizeof (@O_TYPE@)), - D), - d_D (D), - d_symbol_table (symbol_table) -{ -} - -int -@NAME@::work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - assert (noutput_items % d_D == 0); - assert (input_items.size() == output_items.size()); - int nstreams = input_items.size(); - - for (int m=0;m<nstreams;m++) { - const @I_TYPE@ *in = (@I_TYPE@ *) input_items[m]; - @O_TYPE@ *out = (@O_TYPE@ *) output_items[m]; - - // per stream processing - for (int i = 0; i < noutput_items / d_D; i++){ - assert (((unsigned int)in[i]*d_D+d_D) <= d_symbol_table.size()); - memcpy(out, &d_symbol_table[(unsigned int)in[i]*d_D], d_D*sizeof(@O_TYPE@)); - out+=d_D; - } - // end of per stream processing - - } - return noutput_items; -} diff --git a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t deleted file mode 100644 index 17d5688b86..0000000000 --- a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3, or (at your option) - * any later version. - * - * GNU Radio is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -// @WARNING@ - -#ifndef @GUARD_NAME@ -#define @GUARD_NAME@ - -#include <gr_core_api.h> -#include <gr_sync_interpolator.h> - -class @NAME@; -typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; - -GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - -/*! - * \brief Map a stream of symbol indexes (unpacked bytes or shorts) to stream of float or complex onstellation points.in \p D dimensions (\p D = 1 by default) - * \ingroup converter_blk - * - * input: stream of @I_TYPE@; output: stream of @O_TYPE@ - * - * out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 - * - * The combination of gr_packed_to_unpacked_XX followed by - * gr_chunks_to_symbols_XY handles the general case of mapping - * from a stream of bytes or shorts into arbitrary float - * or complex symbols. - * - * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, - * \sa gr_packed_to_unpacked_ss, gr_unpacked_to_packed_ss, - * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. - * \sa gr_chunks_to_symbols_sf, gr_chunks_to_symbols_sc. - */ - -class GR_CORE_API @NAME@ : public gr_sync_interpolator -{ - friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D); - - int d_D; - std::vector<@O_TYPE@> d_symbol_table; - @NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - - public: - int D () const { return d_D; } - std::vector<@O_TYPE@> symbol_table () const { return d_symbol_table; } - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } -}; - -#endif diff --git a/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t index bdd0e810a7..6959eac824 100644 --- a/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t +++ b/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t @@ -29,6 +29,7 @@ #include <algorithm> #include <gr_io_signature.h> #include <stdexcept> +#include <algorithm> #include <gr_complex.h> @@ -64,8 +65,7 @@ int case GR_CONST_WAVE: t = (gr_complex) d_ampl + d_offset; - for (int i = 0; i < noutput_items; i++) // FIXME unroll - optr[i] = t; + std::fill_n(optr, noutput_items, t); break; case GR_SIN_WAVE: @@ -142,8 +142,7 @@ int case GR_CONST_WAVE: t = (@TYPE@) d_ampl + d_offset; - for (int i = 0; i < noutput_items; i++) // FIXME unroll - optr[i] = t; + std::fill_n(optr, noutput_items, t); break; case GR_SIN_WAVE: diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t new file mode 100644 index 0000000000..37963cdfee --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t @@ -0,0 +1,100 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> + +#include <stdio.h> + +@NAME@::@NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset) + : gr_block("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof(@TYPE@)), + gr_make_io_signature (1, 1, sizeof(@TYPE@))), + d_data(data), + d_offset(offset), + d_periodicity(periodicity) +{ + //printf("INITIAL: periodicity = %d, offset = %d\n", periodicity, offset); + // some sanity checks + assert(offset < periodicity); + assert(offset >= 0); + assert(periodicity > data.size()); +} + +int +@NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *out = (@TYPE@ *)output_items[0]; + const @TYPE@ *in = (const @TYPE@ *)input_items[0]; + + int ii(0), oo(0); + + while((oo < noutput_items) && (ii < ninput_items[0])) { + + //printf("oo = %d, ii = %d, d_offset = %d, noutput_items = %d, ninput_items[0] = %d", oo, ii, d_offset, noutput_items, ninput_items[0]); + //printf(", d_periodicity = %d\n", d_periodicity); + + if(d_offset >= ((int)d_data.size())) { // if we are in the copy region + int max_copy = std::min( std::min( noutput_items - oo, ninput_items[0] - ii ), d_periodicity - d_offset ); + //printf("copy %d from input\n", max_copy); + memcpy( &out[oo], &in[ii], sizeof(@TYPE@)*max_copy ); + //printf(" * memcpy returned.\n"); + ii += max_copy; + oo += max_copy; + d_offset = (d_offset + max_copy)%d_periodicity; + + } + else { // if we are in the insertion region + int max_copy = std::min( noutput_items - oo, ((int)d_data.size()) - d_offset ); + //printf("copy %d from d_data[%d] to out[%d]\n", max_copy, d_offset, oo); + memcpy( &out[oo], &d_data[d_offset], sizeof(@TYPE@)*max_copy ); + //printf(" * memcpy returned.\n"); + oo += max_copy; + d_offset = (d_offset + max_copy)%d_periodicity; + //printf(" ## (inelse) oo = %d, d_offset = %d\n", oo, d_offset); + } + + //printf(" # exit else, on to next loop.\n"); + } + //printf(" # got out of loop\n"); + + //printf("consume = %d, produce = %d\n", ii, oo); + consume_each(ii); + return oo; +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, int periodicity, int offset) +{ + return gnuradio::get_initial_sptr(new @NAME@ (data, periodicity, offset)); +} + diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.h.t new file mode 100644 index 0000000000..26f851700d --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.h.t @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_block.h> + +class GR_CORE_API @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief source of @TYPE@'s that gets its data from a vector + * \ingroup source_blk + */ + +class @NAME@ : public gr_block { + friend GR_CORE_API @NAME@_sptr + gr_make_@BASE_NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset); + + std::vector<@TYPE@> d_data; + int d_offset; + int d_periodicity; + + @NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset); + + public: + void rewind() {d_offset=0;} + virtual int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + void set_data(const std::vector<@TYPE@> &data){ d_data = data; rewind(); } +}; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset=0); + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.i.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.i.t index 14c8be4863..f3341eec4f 100644 --- a/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.i.t +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.i.t @@ -1,19 +1,19 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. - * + * Copyright 2012 Free Software Foundation, Inc. + * * This file is part of GNU Radio - * + * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. - * + * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, @@ -24,14 +24,14 @@ GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); -@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, int periodicity, int offset = 0) + throw(std::invalid_argument); -class @NAME@ : public gr_sync_interpolator -{ -private: - @NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D = 1); - -public: - int D () const { return d_D; } - std::vector<@O_TYPE@> symbol_table () const { return d_symbol_table; } +class @NAME@ : public gr_block { + public: + void rewind(); + void set_data(const std::vector<@TYPE@> &data); + private: + @NAME@ (const std::vector<@TYPE@> &data, int periodicity, int offset = 0); }; diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t index fe0a77f818..fe02c1346f 100644 --- a/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t +++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2008 Free Software Foundation, Inc. + * Copyright 2004,2008,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -52,6 +52,7 @@ class @NAME@ : public gr_sync_block { virtual int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + void set_data(const std::vector<@TYPE@> &data){ d_data = data; rewind(); } }; GR_CORE_API @NAME@_sptr diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t index 6c20539ac8..4986c68a35 100644 --- a/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t +++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2008 Free Software Foundation, Inc. + * Copyright 2004,2008,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -30,7 +30,8 @@ gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int v class @NAME@ : public gr_sync_block { public: - void rewind() {d_offset=0;} + void rewind(); + void set_data(const std::vector<@TYPE@> &data); private: @NAME@ (const std::vector<@TYPE@> &data, int vlen); }; diff --git a/gnuradio-core/src/lib/io/gri_wavfile.cc b/gnuradio-core/src/lib/io/gri_wavfile.cc index e316a08254..780bd1b98f 100644 --- a/gnuradio-core/src/lib/io/gri_wavfile.cc +++ b/gnuradio-core/src/lib/io/gri_wavfile.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2008 Free Software Foundation, Inc. + * Copyright 2004,2008,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,107 +27,30 @@ #include <gri_wavfile.h> #include <cstring> #include <stdint.h> +#include <boost/asio.hpp> # define VALID_COMPRESSION_TYPE 0x0001 // WAV files are always little-endian, so we need some byte switching macros -// FIXME: Use libgruel versions - +// Basically, this is the opposite of htonx() and ntohx() #ifdef WORDS_BIGENDIAN -#ifdef HAVE_BYTESWAP_H -#include <byteswap.h> -#else -#warning Using non-portable code (likely wrong other than ILP32). - -static inline short int -bswap_16 (unsigned short int x) -{ - return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)); -} - -static inline unsigned int -bswap_32 (unsigned int x) -{ - return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ - | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)); -} -#endif // HAVE_BYTESWAP_H - -static inline uint32_t -host_to_wav(uint32_t x) -{ - return bswap_32(x); -} - -static inline uint16_t -host_to_wav(uint16_t x) -{ - return bswap_16(x); -} - -static inline int16_t -host_to_wav(int16_t x) -{ - return bswap_16(x); -} - -static inline uint32_t -wav_to_host(uint32_t x) -{ - return bswap_32(x); -} - -static inline uint16_t -wav_to_host(uint16_t x) -{ - return bswap_16(x); -} - -static inline int16_t -wav_to_host(int16_t x) -{ - return bswap_16(x); -} +static inline uint32_t host_to_wav(uint32_t x) { return htonl(x); } +static inline uint16_t host_to_wav(uint16_t x) { return htons(x); } +static inline int16_t host_to_wav(int16_t x) { return htons(x); } +static inline uint32_t wav_to_host(uint32_t x) { return ntohl(x); } +static inline uint16_t wav_to_host(uint16_t x) { return ntohs(x); } +static inline int16_t wav_to_host(int16_t x) { return ntohs(x); } #else -static inline uint32_t -host_to_wav(uint32_t x) -{ - return x; -} - -static inline uint16_t -host_to_wav(uint16_t x) -{ - return x; -} - -static inline int16_t -host_to_wav(int16_t x) -{ - return x; -} - -static inline uint32_t -wav_to_host(uint32_t x) -{ - return x; -} - -static inline uint16_t -wav_to_host(uint16_t x) -{ - return x; -} - -static inline int16_t -wav_to_host(int16_t x) -{ - return x; -} +static inline uint32_t host_to_wav(uint32_t x) { return x; } +static inline uint16_t host_to_wav(uint16_t x) { return x; } +static inline int16_t host_to_wav(int16_t x) { return x; } +static inline uint32_t wav_to_host(uint32_t x) { return x; } +static inline uint16_t wav_to_host(uint16_t x) { return x; } +static inline int16_t wav_to_host(int16_t x) { return x; } #endif // WORDS_BIGENDIAN @@ -225,12 +148,15 @@ gri_wavheader_parse(FILE *fp, short int gri_wav_read_sample(FILE *fp, int bytes_per_sample) { - int16_t buf = 0; - size_t fresult; - - fresult = fread(&buf, bytes_per_sample, 1, fp); + int16_t buf_16bit; - return (short) wav_to_host(buf); + if(!fread(&buf_16bit, bytes_per_sample, 1, fp)) { + return 0; + } + if(bytes_per_sample == 1) { + return (short) buf_16bit; + } + return (short)wav_to_host(buf_16bit); } diff --git a/gnuradio-core/src/lib/io/gri_wavfile.h b/gnuradio-core/src/lib/io/gri_wavfile.h index c757be26bc..16280e34a9 100644 --- a/gnuradio-core/src/lib/io/gri_wavfile.h +++ b/gnuradio-core/src/lib/io/gri_wavfile.h @@ -29,20 +29,15 @@ /*! * \brief Read signal information from a given WAV file. * - * \p fp File pointer to an opened, empty file. - * \p sample_rate Stores the sample rate [S/s] - * \p nchans Number of channels - * \p bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding to - * 8 or 16 bit samples, respectively) - * \p first_sample_pos Number of the first byte containing a sample. Use this - * with fseek() to jump from the end of the file to the first sample - * when in repeat mode. - * \p samples_per_chan Number of samples per channel - * \p normalize_fac The normalization factor with which you need to divide the - * integer values of the samples to get them within [-1;1] - * \p normalize_shift The value by which the sample values need to be shifted - * after normalization (reason being, 8-bit WAV files store samples as - * unsigned char and 16-bit as signed short int) + * \param[in] fp File pointer to an opened, empty file. + * \param[out] sample_rate Stores the sample rate [S/s] + * \param[out] nchans Number of channels + * \param[out] bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding o + * 8 or 16 bit samples, respectively) + * \param[out] first_sample_pos Number of the first byte containing a sample. Use this + * with fseek() to jump from the end of the file to the + * first sample when in repeat mode. + * \param[out] samples_per_chan Number of samples per channel * \return True on a successful read, false if the file could not be read or is * not a valid WAV file. */ @@ -94,8 +89,8 @@ gri_wav_write_sample(FILE *fp, short int sample, int bytes_per_sample); * shouldn't happen), you need to fseek() to the end of the file (or * whereever). * - * \p fp File pointer to an open WAV file with a blank header - * \p byte_count Length of all samples written to the file in bytes. + * \param[in] fp File pointer to an open WAV file with a blank header + * \param[in] byte_count Length of all samples written to the file in bytes. */ bool gri_wavheader_complete(FILE *fp, unsigned int byte_count); diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.i b/gnuradio-core/src/lib/runtime/gr_top_block.i index 80a1b82aea..6ae4c65a99 100644 --- a/gnuradio-core/src/lib/runtime/gr_top_block.i +++ b/gnuradio-core/src/lib/runtime/gr_top_block.i @@ -20,8 +20,6 @@ * Boston, MA 02110-1301, USA. */ -%include <gr_top_block.i> - class gr_top_block; typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; %template(gr_top_block_sptr) boost::shared_ptr<gr_top_block>; diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py index ce07579123..77bf0607a3 100644 --- a/gnuradio-core/src/python/build_utils.py +++ b/gnuradio-core/src/python/build_utils.py @@ -182,7 +182,7 @@ def standard_dict (name, code3, package='gr'): d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper () d['BASE_NAME'] = re.sub ('^' + package + '_', '', name) d['SPTR_NAME'] = '%s_sptr' % name - d['WARNING'] = 'WARNING: this file is machine generated. Edits will be over written' + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' d['COPYRIGHT'] = copyright d['TYPE'] = i_type (code3) d['I_TYPE'] = i_type (code3) @@ -190,3 +190,35 @@ def standard_dict (name, code3, package='gr'): d['TAP_TYPE'] = tap_type (code3) d['IS_COMPLEX'] = is_complex (code3) return d + + +def standard_dict2 (name, code3, package): + d = {} + d['NAME'] = name + d['BASE_NAME'] = name + d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' + d['COPYRIGHT'] = copyright + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d + +def standard_impl_dict2 (name, code3, package): + d = {} + d['NAME'] = name + d['IMPL_NAME'] = name + d['BASE_NAME'] = name.rstrip("_impl") + d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' + d['COPYRIGHT'] = copyright + d['FIR_TYPE'] = "fir_filter_" + code3 + d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c' + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py deleted file mode 100755 index c1fe2a7000..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2006,2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import math -import random - -def make_random_int_tuple(L, min, max): - result = [] - for x in range(L): - result.append(random.randint(min, max)) - return tuple(result) - - -class test_diff_encoder (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_diff_encdec_000(self): - random.seed(0) - modulus = 2 - src_data = make_random_int_tuple(1000, 0, modulus-1) - expected_result = src_data - src = gr.vector_source_b(src_data) - enc = gr.diff_encoder_bb(modulus) - dec = gr.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() - self.tb.connect(src, enc, dec, dst) - self.tb.run() # run the graph and wait for it to finish - actual_result = dst.data() # fetch the contents of the sink - self.assertEqual(expected_result, actual_result) - - def test_diff_encdec_001(self): - random.seed(0) - modulus = 4 - src_data = make_random_int_tuple(1000, 0, modulus-1) - expected_result = src_data - src = gr.vector_source_b(src_data) - enc = gr.diff_encoder_bb(modulus) - dec = gr.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() - self.tb.connect(src, enc, dec, dst) - self.tb.run() # run the graph and wait for it to finish - actual_result = dst.data() # fetch the contents of the sink - self.assertEqual(expected_result, actual_result) - - def test_diff_encdec_002(self): - random.seed(0) - modulus = 8 - src_data = make_random_int_tuple(40000, 0, modulus-1) - expected_result = src_data - src = gr.vector_source_b(src_data) - enc = gr.diff_encoder_bb(modulus) - dec = gr.diff_decoder_bb(modulus) - dst = gr.vector_sink_b() - self.tb.connect(src, enc, dec, dst) - self.tb.run() # run the graph and wait for it to finish - actual_result = dst.data() # fetch the contents of the sink - self.assertEqual(expected_result, actual_result) - -if __name__ == '__main__': - gr_unittest.run(test_diff_encoder, "test_diff_encoder.xml") - diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py deleted file mode 100755 index 95b8c06641..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2004,2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest -import math - -def sincos(x): - return math.cos(x) + math.sin(x) * 1j - -class test_bytes_to_syms (gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_bytes_to_syms_001 (self): - src_data = (0x01, 0x80, 0x03) - expected_result = (-1, -1, -1, -1, -1, -1, -1, +1, - +1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, +1, +1) - src = gr.vector_source_b (src_data) - op = gr.bytes_to_syms () - dst = gr.vector_sink_f () - self.tb.connect (src, op) - self.tb.connect (op, dst) - self.tb.run () - result_data = dst.data () - self.assertEqual (expected_result, result_data) - - def test_simple_framer (self): - src_data = (0x00, 0x11, 0x22, 0x33, - 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, - 0xcc, 0xdd, 0xee, 0xff) - - expected_result = ( - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x00, 0x00, 0x11, 0x22, 0x33, 0x55, - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x01, 0x44, 0x55, 0x66, 0x77, 0x55, - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x02, 0x88, 0x99, 0xaa, 0xbb, 0x55, - 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x03, 0xcc, 0xdd, 0xee, 0xff, 0x55) - - src = gr.vector_source_b (src_data) - op = gr.simple_framer (4) - dst = gr.vector_sink_b () - self.tb.connect (src, op) - self.tb.connect (op, dst) - self.tb.run () - result_data = dst.data () - self.assertEqual (expected_result, result_data) - - -if __name__ == '__main__': - gr_unittest.run(test_bytes_to_syms, "test_bytes_to_syms.xml") - diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py deleted file mode 100755 index 161e4a5cc1..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class test_glfsr_source(gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block () - - def tearDown (self): - self.tb = None - - def test_000_make_b(self): - src = gr.glfsr_source_b(16) - self.assertEquals(src.mask(), 0x8016) - self.assertEquals(src.period(), 2**16-1) - - def test_001_degree_b(self): - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(0)) - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(33)) - - def test_002_correlation_b(self): - for degree in range(1,11): # Higher degrees take too long to correlate - src = gr.glfsr_source_b(degree, False) - b2f = gr.chunks_to_symbols_bf((-1.0,1.0), 1) - dst = gr.vector_sink_f() - del self.tb # Discard existing top block - self.tb = gr.top_block() - self.tb.connect(src, b2f, dst) - self.tb.run() - self.tb.disconnect_all() - actual_result = dst.data() - R = auto_correlate(actual_result) - self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin - for i in range(len(R)-1): - self.assertEqual(R[i+1], -1.0) # Auto-correlation minimum everywhere else - - def test_003_make_f(self): - src = gr.glfsr_source_f(16) - self.assertEquals(src.mask(), 0x8016) - self.assertEquals(src.period(), 2**16-1) - - def test_004_degree_f(self): - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(0)) - self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(33)) - def test_005_correlation_f(self): - for degree in range(1,11): # Higher degrees take too long to correlate - src = gr.glfsr_source_f(degree, False) - dst = gr.vector_sink_f() - del self.tb # Discard existing top block - self.tb = gr.top_block() - self.tb.connect(src, dst) - self.tb.run() - - actual_result = dst.data() - R = auto_correlate(actual_result) - self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin - for i in range(len(R)-1): - self.assertEqual(R[i+1], -1.0) # Auto-correlation minimum everywhere else - -def auto_correlate(data): - l = len(data) - R = [0,]*l - for lag in range(l): - for i in range(l): - R[lag] += data[i]*data[i-lag] - return R - -if __name__ == '__main__': - gr_unittest.run(test_glfsr_source, "test_glfsr_source.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_keep_m_in_n.py b/gnuradio-core/src/python/gnuradio/gr/qa_keep_m_in_n.py new file mode 100755 index 0000000000..922671d024 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_keep_m_in_n.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2008,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gr_unittest +import sys +import random + +class test_keep_m_in_n(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_001(self): + self.maxDiff = None; + tb = gr.top_block() + src = gr.vector_source_b( range(0,100) ) + + # itemsize, M, N, offset + km2 = gr.keep_m_in_n( 1, 1, 2, 0 ); + km3 = gr.keep_m_in_n( 1, 1, 3, 1 ); + km7 = gr.keep_m_in_n( 1, 1, 7, 2 ); + snk2 = gr.vector_sink_b(); + snk3 = gr.vector_sink_b(); + snk7 = gr.vector_sink_b(); + tb.connect(src,km2,snk2); + tb.connect(src,km3,snk3); + tb.connect(src,km7,snk7); + tb.run(); + + self.assertEqual(range(0,100,2), list(snk2.data())); + self.assertEqual(range(1,100,3), list(snk3.data())); + self.assertEqual(range(2,100,7), list(snk7.data())); + + +if __name__ == '__main__': + gr_unittest.run(test_keep_m_in_n, "test_keep_m_in_n.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py new file mode 100755 index 0000000000..25fc5e9fcc --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# +# Copyright 2006,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import random + +class test_pack(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_001(self): + src_data = (1,0,1,1,0,1,1,0) + expected_results = (1,0,1,1,0,1,1,0) + src = gr.vector_source_b(src_data,False) + op = gr.pack_k_bits_bb(1) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + src_data = (1,0,1,1,0,0,0,1) + expected_results = ( 2, 3, 0, 1) + src = gr.vector_source_b(src_data,False) + op = gr.pack_k_bits_bb(2) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + #self.assertEqual(expected_results, dst.data()) + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + src_data = expected_results = map(lambda x: random.randint(0,3), range(10)); + src = gr.vector_source_b( src_data ); + pack = gr.pack_k_bits_bb(2); + unpack = gr.unpack_k_bits_bb(2); + snk = gr.vector_sink_b(); + self.tb.connect(src,unpack,pack,snk); + self.tb.run() + self.assertEqual(list(expected_results), list(snk.data())); + +if __name__ == '__main__': + gr_unittest.run(test_pack, "test_pack.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py b/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py deleted file mode 100755 index 5fe89bdc7f..0000000000 --- a/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008,2010 Free Software Foundation, Inc. -# -# This file is part of GNU Radio -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GNU Radio; see the file COPYING. If not, write to -# the Free Software Foundation, Inc., 51 Franklin Street, -# Boston, MA 02110-1301, USA. -# - -from gnuradio import gr, gr_unittest - -class test_scrambler(gr_unittest.TestCase): - - def setUp (self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_scrambler_descrambler(self): - src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) - scrambler = gr.scrambler_bb(0x8a, 0x7F, 7) # CCSDS 7-bit scrambler - descrambler = gr.descrambler_bb(0x8a, 0x7F, 7) - dst = gr.vector_sink_b() - self.tb.connect(src, scrambler, descrambler, dst) - self.tb.run() - self.assertEqual(tuple(src_data[:-8]), dst.data()[8:]) # skip garbage during synchronization - - def test_additive_scrambler(self): - src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) - scrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7) - descrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7) - dst = gr.vector_sink_b() - self.tb.connect(src, scrambler, descrambler, dst) - self.tb.run() - self.assertEqual(src_data, dst.data()) - - def test_additive_scrambler_reset(self): - src_data = (1,)*1000 - src = gr.vector_source_b(src_data, False) - scrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7, 100) - descrambler = gr.additive_scrambler_bb(0x8a, 0x7f, 7, 100) - dst = gr.vector_sink_b() - self.tb.connect(src, scrambler, descrambler, dst) - self.tb.run() - self.assertEqual(src_data, dst.data()) - -if __name__ == '__main__': - gr_unittest.run(test_scrambler, "test_scrambler.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pn_correlator_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py index 6a62a6997b..81babca048 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_pn_correlator_cc.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2007,2010 Free Software Foundation, Inc. +# Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,29 +22,22 @@ from gnuradio import gr, gr_unittest -class test_pn_correlator_cc(gr_unittest.TestCase): +class test_tag_debug(gr_unittest.TestCase): def setUp(self): - self.tb = gr.top_block () + self.tb = gr.top_block() def tearDown(self): self.tb = None - def test_000_make(self): - c = gr.pn_correlator_cc(10) - - def test_001_correlate(self): - degree = 10 - length = 2**degree-1 - src = gr.glfsr_source_f(degree) - head = gr.head(gr.sizeof_float, length*length) - f2c = gr.float_to_complex() - corr = gr.pn_correlator_cc(degree) - dst = gr.vector_sink_c() - self.tb.connect(src, head, f2c, corr, dst) + def test_001(self): + # Just run some data through and make sure it doesn't puke. + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + src = gr.vector_source_i(src_data) + op = gr.tag_debug(gr.sizeof_int, "tag QA") + self.tb.connect(src, op) self.tb.run() - data = dst.data() - self.assertEqual(data[-1], (1.0+0j)) + x = op.current_tags() if __name__ == '__main__': - gr_unittest.run(test_pn_correlator_cc, "test_pn_correlator_cc.xml") + gr_unittest.run(test_tag_debug, "test_tag_debug.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_vector_insert.py index 41f96aa616..acc06dfded 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_vector_insert.py @@ -1,29 +1,29 @@ #!/usr/bin/env python # -# Copyright 2004,2007,2010 Free Software Foundation, Inc. -# +# Copyright 2012 Free Software Foundation, Inc. +# # This file is part of GNU Radio -# +# # GNU Radio is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. -# +# # GNU Radio is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -# +# from gnuradio import gr, gr_unittest import math -class test_diff_phasor (gr_unittest.TestCase): +class test_vector_insert(gr_unittest.TestCase): def setUp (self): self.tb = gr.top_block () @@ -31,20 +31,28 @@ class test_diff_phasor (gr_unittest.TestCase): def tearDown (self): self.tb = None - def test_diff_phasor_cc (self): - src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j) - expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j) - src = gr.vector_source_c (src_data) - op = gr.diff_phasor_cc () - dst = gr.vector_sink_c () - self.tb.connect (src, op) - self.tb.connect (op, dst) - self.tb.run () # run the graph and wait for it to finish - actual_result = dst.data () # fetch the contents of the sink - self.assertComplexTuplesAlmostEqual (expected_result, actual_result) + def test_001(self): + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + + period = 9177; + offset = 0; + + src = gr.null_source(1) + head = gr.head(1, 10000000); + ins = gr.vector_insert_b([1], period, offset); + dst = gr.vector_sink_b() + self.tb.connect(src, head, ins, dst) + self.tb.run() + result_data = dst.data() + for i in range(10000): + if(i%period == offset): + self.assertEqual(1, result_data[i]) + else: + self.assertEqual(0, result_data[i]) if __name__ == '__main__': - gr_unittest.run(test_diff_phasor, "test_diff_phasor.xml") + gr_unittest.run(test_vector_insert, "test_vector_insert.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_vector_map.py b/gnuradio-core/src/python/gnuradio/gr/qa_vector_map.py new file mode 100644 index 0000000000..12f4be5898 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_vector_map.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import math + +class test_vector_map(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_reversing(self): + # Chunk data in blocks of N and reverse the block contents. + N = 5 + src_data = range(0, 20) + expected_result = [] + for i in range(N-1, len(src_data), N): + for j in range(0, N): + expected_result.append(1.0*(i-j)) + mapping = [list(reversed([(0, i) for i in range(0, N)]))] + src = gr.vector_source_f(src_data, False, N) + vmap = gr.vector_map(gr.sizeof_float, (N, ), mapping) + dst = gr.vector_sink_f(N) + self.tb.connect(src, vmap, dst) + self.tb.run() + result_data = list(dst.data()) + self.assertEqual(expected_result, result_data) + + def test_vector_to_streams(self): + # Split an input vector into N streams. + N = 5 + M = 20 + src_data = range(0, M) + expected_results = [] + for n in range(0, N): + expected_results.append(range(n, M, N)) + mapping = [[(0, n)] for n in range(0, N)] + src = gr.vector_source_f(src_data, False, N) + vmap = gr.vector_map(gr.sizeof_float, (N, ), mapping) + dsts = [gr.vector_sink_f(1) for n in range(0, N)] + self.tb.connect(src, vmap) + for n in range(0, N): + self.tb.connect((vmap, n), dsts[n]) + self.tb.run() + for n in range(0, N): + result_data = list(dsts[n].data()) + self.assertEqual(expected_results[n], result_data) + + def test_interleaving(self): + # Takes 3 streams (a, b and c) + # Outputs 2 streams. + # First (d) is interleaving of a and b. + # Second (e) is interleaving of a and b and c. c is taken in + # chunks of 2 which are reversed. + A = (1, 2, 3, 4, 5) + B = (11, 12, 13, 14, 15) + C = (99, 98, 97, 96, 95, 94, 93, 92, 91, 90) + expected_D = (1, 11, 2, 12, 3, 13, 4, 14, 5, 15) + expected_E = (1, 11, 98, 99, 2, 12, 96, 97, 3, 13, 94, 95, + 4, 14, 92, 93, 5, 15, 90, 91) + mapping = [[(0, 0), (1, 0)], # mapping to produce D + [(0, 0), (1, 0), (2, 1), (2, 0)], # mapping to produce E + ] + srcA = gr.vector_source_f(A, False, 1) + srcB = gr.vector_source_f(B, False, 1) + srcC = gr.vector_source_f(C, False, 2) + vmap = gr.vector_map(gr.sizeof_int, (1, 1, 2), mapping) + dstD = gr.vector_sink_f(2) + dstE = gr.vector_sink_f(4) + self.tb.connect(srcA, (vmap, 0)) + self.tb.connect(srcB, (vmap, 1)) + self.tb.connect(srcC, (vmap, 2)) + self.tb.connect((vmap, 0), dstD) + self.tb.connect((vmap, 1), dstE) + self.tb.run() + self.assertEqual(expected_D, dstD.data()) + self.assertEqual(expected_E, dstE.data()) + + + +if __name__ == '__main__': + gr_unittest.run(test_vector_map, "test_vector_map.xml") + diff --git a/gr-audio/examples/python/noise.py b/gr-audio/examples/python/noise.py index 12eee1906d..bba9e83eae 100755 --- a/gr-audio/examples/python/noise.py +++ b/gr-audio/examples/python/noise.py @@ -22,6 +22,7 @@ from gnuradio import gr from gnuradio import audio +from gnuradio import digital from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -44,7 +45,7 @@ class my_top_block(gr.top_block): ampl = 0.1 src = gr.glfsr_source_b(32) # Pseudorandom noise source - b2f = gr.chunks_to_symbols_bf([ampl, -ampl], 1) + b2f = digital.chunks_to_symbols_bf([ampl, -ampl], 1) dst = audio.sink(sample_rate, options.audio_output) self.connect(src, b2f, dst) diff --git a/gr-audio/lib/CMakeLists.txt b/gr-audio/lib/CMakeLists.txt index 7e0252a8b1..c1781af79e 100644 --- a/gr-audio/lib/CMakeLists.txt +++ b/gr-audio/lib/CMakeLists.txt @@ -150,4 +150,4 @@ add_library(gnuradio-audio SHARED ${gr_audio_sources}) target_link_libraries(gnuradio-audio ${gr_audio_libs}) GR_LIBRARY_FOO(gnuradio-audio RUNTIME_COMPONENT "audio_runtime" DEVEL_COMPONENT "audio_devel") -install(FILES ${gr_audio_confs} DESTINATION ${GR_PKG_CONF_DIR} COMPONENT "audio_runtime") +install(FILES ${gr_audio_confs} DESTINATION ${GR_PREFSDIR} COMPONENT "audio_runtime") diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py index ab7e988eba..daefc5116d 100755 --- a/gr-digital/examples/narrowband/digital_bert_rx.py +++ b/gr-digital/examples/narrowband/digital_bert_rx.py @@ -78,10 +78,10 @@ class bert_receiver(gr.hier_block2): self.connect(self._demod.time_recov, self._snr_probe) # Descramble BERT sequence. A channel error will create 3 incorrect bits - self._descrambler = gr.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler + self._descrambler = digital.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler # Measure BER by the density of 0s in the stream - self._ber = gr.probe_density_b(1.0/self._symbol_rate) + self._ber = digital.probe_density_b(1.0/self._symbol_rate) self.connect(self, self._demod, self._descrambler, self._ber) diff --git a/gr-digital/examples/narrowband/digital_bert_tx.py b/gr-digital/examples/narrowband/digital_bert_tx.py index f29e997af6..7caccdf42b 100755 --- a/gr-digital/examples/narrowband/digital_bert_tx.py +++ b/gr-digital/examples/narrowband/digital_bert_tx.py @@ -43,7 +43,7 @@ class bert_transmit(gr.hier_block2): # Create BERT data bit stream self._bits = gr.vector_source_b([1,], True) # Infinite stream of ones - self._scrambler = gr.scrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit scrambler + self._scrambler = digital.scrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit scrambler self._mod = digital.generic_mod(constellation, samples_per_symbol, differential, excess_bw, gray_coded, diff --git a/gr-digital/grc/digital_dxpsk_demod.xml b/gr-digital/grc/digital_dxpsk_demod.xml index cfd474f68f..35704eeb67 100644 --- a/gr-digital/grc/digital_dxpsk_demod.xml +++ b/gr-digital/grc/digital_dxpsk_demod.xml @@ -23,7 +23,7 @@ <!-- ################################################### -##DPSK2 Mod - 2, 4, 8 +##DPSK2 Mod - 2, 4 ################################################### --> <block> @@ -36,7 +36,7 @@ freq_bw=$freq_bw, phase_bw=$phase_bw, timing_bw=$timing_bw, - gray_coded=$gray_coded, + mod_code=$mod_code, verbose=$verbose, log=$log )</make> @@ -93,16 +93,15 @@ </param> <param> <name>Gray Code</name> - <key>gray_coded</key> - <value>True</value> - <type>bool</type> + <key>mod_code</key> + <type>enum</type> <option> <name>Yes</name> - <key>True</key> + <key>"gray"</key> </option> <option> <name>No</name> - <key>False</key> + <key>"none"</key> </option> </param> <param> diff --git a/gr-digital/grc/digital_dxpsk_mod.xml b/gr-digital/grc/digital_dxpsk_mod.xml index fbda9fb1f9..060edb9081 100644 --- a/gr-digital/grc/digital_dxpsk_mod.xml +++ b/gr-digital/grc/digital_dxpsk_mod.xml @@ -23,7 +23,7 @@ <!-- ################################################### -## DPSK Mod - 2, 4, 8 +## DPSK Mod - 2, 4 ################################################### --> <block> @@ -33,7 +33,7 @@ <make>digital.$(type)_mod( samples_per_symbol=$samples_per_symbol, excess_bw=$excess_bw, - gray_coded=$gray_coded, + mod_code=$mod_code, verbose=$verbose, log=$log) </make> @@ -49,10 +49,6 @@ <name>DQPSK</name> <key>dqpsk</key> </option> - <option> - <name>D8PSK</name> - <key>d8psk</key> - </option> </param> <param> <name>Samples/Symbol</name> @@ -68,16 +64,16 @@ </param> <param> <name>Gray Code</name> - <key>gray_coded</key> - <value>True</value> - <type>bool</type> + <key>mod_code</key> + <value>"gray"</value> + <type>enum</type> <option> <name>Yes</name> - <key>True</key> + <key>"gray"</key> </option> <option> <name>No</name> - <key>False</key> + <key>"none"</key> </option> </param> <param> diff --git a/gr-digital/grc/digital_mpsk_receiver_cc.xml b/gr-digital/grc/digital_mpsk_receiver_cc.xml index ab7e5c2091..bd738fccc3 100644 --- a/gr-digital/grc/digital_mpsk_receiver_cc.xml +++ b/gr-digital/grc/digital_mpsk_receiver_cc.xml @@ -7,7 +7,7 @@ <block> <name>MPSK Receiver</name> <key>digital_mpsk_receiver_cc</key> - <import>from gnuradio import digital</import> + <import>from gnuradio import digital;import cmath</import> <make>digital.mpsk_receiver_cc($M, $theta, $w, $fmin, $fmax, $mu, $gain_mu, $omega, $gain_omega, $omega_relative_limit)</make> <callback>set_loop_bandwidth($w)</callback> <callback>set_mu($mu)</callback> @@ -17,51 +17,61 @@ <param> <name>M</name> <key>M</key> + <value>4</value> <type>int</type> </param> <param> <name>Theta</name> <key>theta</key> + <value>0</value> <type>real</type> </param> <param> <name>Loop Bandwidth</name> <key>w</key> + <value>cmath.pi/100.0</value> <type>real</type> </param> <param> <name>Min Freq</name> <key>fmin</key> + <value>-0.5</value> <type>real</type> </param> <param> <name>Max Freq</name> <key>fmax</key> + <value>0.5</value> <type>real</type> </param> <param> <name>Mu</name> <key>mu</key> + <value>0.25</value> <type>real</type> </param> <param> <name>Gain Mu</name> <key>gain_mu</key> + <value>0.01</value> <type>real</type> </param> <param> <name>Omega</name> <key>omega</key> + <value>2</value> <type>real</type> </param> <param> <name>Gain Omega</name> <key>gain_omega</key> + <value>0.001</value> <type>real</type> </param> <param> <name>Omega Relative Limit</name> <key>omega_relative_limit</key> + <value>0.001</value> <type>real</type> </param> <sink> @@ -72,4 +82,5 @@ <name>out</name> <type>complex</type> </source> + </block> diff --git a/gr-digital/grc/digital_ofdm_insert_preamble.xml b/gr-digital/grc/digital_ofdm_insert_preamble.xml index 33a93058f9..9ad8fa793b 100644 --- a/gr-digital/grc/digital_ofdm_insert_preamble.xml +++ b/gr-digital/grc/digital_ofdm_insert_preamble.xml @@ -48,10 +48,16 @@ <sink> <name>flag</name> <type>byte</type> + <optional>1</optional> </sink> <source> <name>out</name> <type>complex</type> <vlen>$fft_length</vlen> </source> + <source> + <name>flag</name> + <type>byte</type> + <optional>1</optional> + </source> </block> diff --git a/gr-digital/grc/digital_psk_demod.xml b/gr-digital/grc/digital_psk_demod.xml index 7e0773a986..2e0e86ebc6 100644 --- a/gr-digital/grc/digital_psk_demod.xml +++ b/gr-digital/grc/digital_psk_demod.xml @@ -37,7 +37,7 @@ excess_bw=$excess_bw, phase_bw=$phase_bw, timing_bw=$timing_bw, - gray_coded=$gray_coded, + mod_code=$mod_code, verbose=$verbose, log=$log, )</make> @@ -93,7 +93,7 @@ </param> <param> <name>Gray Code</name> - <key>gray_coded</key> + <key>mod_code</key> <type>enum</type> <option> <name>Yes</name> diff --git a/gr-digital/grc/digital_qam_demod.xml b/gr-digital/grc/digital_qam_demod.xml index 86080fff79..5aaec1bd0a 100644 --- a/gr-digital/grc/digital_qam_demod.xml +++ b/gr-digital/grc/digital_qam_demod.xml @@ -38,7 +38,7 @@ freq_bw=$freq_bw, timing_bw=$timing_bw, phase_bw=$phase_bw, - gray_coded=$gray_coded, + mod_code=$mod_code, verbose=$verbose, log=$log, )</make> diff --git a/gr-digital/grc/digital_simple_framer.xml b/gr-digital/grc/digital_simple_framer.xml index bbeed32d3e..2d57222f3b 100644 --- a/gr-digital/grc/digital_simple_framer.xml +++ b/gr-digital/grc/digital_simple_framer.xml @@ -7,8 +7,8 @@ <block> <name>Simple Framer</name> <key>digital_simple_framer</key> - <import>from gnuradio import gr</import> - <make>gr.simple_framer($payload_bytesize)</make> + <import>from gnuradio import digital</import> + <make>digital.simple_framer($payload_bytesize)</make> <param> <name>Payload Byte Size</name> <key>payload_bytesize</key> diff --git a/gr-digital/include/digital_bytes_to_syms.h b/gr-digital/include/digital_bytes_to_syms.h index 3062366b95..c1857c8cf2 100644 --- a/gr-digital/include/digital_bytes_to_syms.h +++ b/gr-digital/include/digital_bytes_to_syms.h @@ -39,12 +39,12 @@ DIGITAL_API digital_bytes_to_syms_sptr digital_make_bytes_to_syms(); * This block is deprecated. * * The combination of gr_packed_to_unpacked_bb followed by - * gr_chunks_to_symbols_bf or gr_chunks_to_symbols_bc handles the + * digital_chunks_to_symbols_bf or digital_chunks_to_symbols_bc handles the * general case of mapping from a stream of bytes into arbitrary float * or complex symbols. * * \sa gr_packed_to_unpacked_bb, gr_unpacked_to_packed_bb, - * \sa gr_chunks_to_symbols_bf, gr_chunks_to_symbols_bc. + * \sa digital_chunks_to_symbols_bf, digital_chunks_to_symbols_bc. */ class DIGITAL_API digital_bytes_to_syms : public gr_sync_interpolator { diff --git a/gr-digital/include/digital_chunks_to_symbols_XX.h.t b/gr-digital/include/digital_chunks_to_symbols_XX.h.t index 92b7c94d58..3a82c68070 100644 --- a/gr-digital/include/digital_chunks_to_symbols_XX.h.t +++ b/gr-digital/include/digital_chunks_to_symbols_XX.h.t @@ -43,7 +43,7 @@ digital_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D * out[n D + k] = symbol_table[in[n] D + k], k=0,1,...,D-1 * * The combination of gr_packed_to_unpacked_XX followed by - * gr_chunks_to_symbols_XY handles the general case of mapping + * digital_chunks_to_symbols_XY handles the general case of mapping * from a stream of bytes or shorts into arbitrary float * or complex symbols. * diff --git a/gr-digital/include/digital_framer_sink_1.h b/gr-digital/include/digital_framer_sink_1.h index bb82bf5a73..51d872d874 100644 --- a/gr-digital/include/digital_framer_sink_1.h +++ b/gr-digital/include/digital_framer_sink_1.h @@ -37,7 +37,7 @@ digital_make_framer_sink_1(gr_msg_queue_sptr target_queue); * \brief Given a stream of bits and access_code flags, assemble packets. * \ingroup sink_blk * - * input: stream of bytes from gr_correlate_access_code_bb + * input: stream of bytes from digital_correlate_access_code_bb * output: none. Pushes assembled packet into target queue * * The framer expects a fixed length header of 2 16-bit shorts diff --git a/gr-digital/include/digital_glfsr_source_b.h b/gr-digital/include/digital_glfsr_source_b.h index 92e5e81f5c..151e5a296c 100644 --- a/gr-digital/include/digital_glfsr_source_b.h +++ b/gr-digital/include/digital_glfsr_source_b.h @@ -26,7 +26,7 @@ #include <digital_api.h> #include <gr_sync_block.h> -class gri_glfsr; +class digital_impl_glfsr; class digital_glfsr_source_b; typedef boost::shared_ptr<digital_glfsr_source_b> digital_glfsr_source_b_sptr; @@ -54,7 +54,7 @@ class DIGITAL_API digital_glfsr_source_b : public gr_sync_block digital_make_glfsr_source_b(int degree, bool repeat, int mask, int seed); - gri_glfsr *d_glfsr; + digital_impl_glfsr *d_glfsr; bool d_repeat; unsigned int d_index; diff --git a/gr-digital/include/digital_glfsr_source_f.h b/gr-digital/include/digital_glfsr_source_f.h index 77d7b0f741..fb5b064e4f 100644 --- a/gr-digital/include/digital_glfsr_source_f.h +++ b/gr-digital/include/digital_glfsr_source_f.h @@ -26,7 +26,7 @@ #include <digital_api.h> #include <gr_sync_block.h> -class gri_glfsr; +class digital_impl_glfsr; class digital_glfsr_source_f; typedef boost::shared_ptr<digital_glfsr_source_f> digital_glfsr_source_f_sptr; @@ -54,7 +54,7 @@ class DIGITAL_API digital_glfsr_source_f : public gr_sync_block digital_make_glfsr_source_f(int degree, bool repeat, int mask, int seed); - gri_glfsr *d_glfsr; + digital_impl_glfsr *d_glfsr; bool d_repeat; unsigned int d_index; diff --git a/gr-digital/include/digital_ofdm_insert_preamble.h b/gr-digital/include/digital_ofdm_insert_preamble.h index 6f9dae5d6b..fa44558add 100644 --- a/gr-digital/include/digital_ofdm_insert_preamble.h +++ b/gr-digital/include/digital_ofdm_insert_preamble.h @@ -88,18 +88,20 @@ private: int d_pending_flag; void enter_idle(); - void enter_preamble(); void enter_first_payload(); void enter_payload(); public: ~digital_ofdm_insert_preamble(); + void enter_preamble(); int general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + }; #endif /* INCLUDED_DIGITAL_OFDM_INSERT_PREAMBLE_H */ diff --git a/gr-digital/include/digital_pn_correlator_cc.h b/gr-digital/include/digital_pn_correlator_cc.h index 87cc2ff93c..407cc1e67b 100644 --- a/gr-digital/include/digital_pn_correlator_cc.h +++ b/gr-digital/include/digital_pn_correlator_cc.h @@ -25,7 +25,7 @@ #include <digital_api.h> #include <gr_sync_decimator.h> -#include <gri_glfsr.h> +#include <digital_impl_glfsr.h> class digital_pn_correlator_cc; typedef boost::shared_ptr<digital_pn_correlator_cc> digital_pn_correlator_cc_sptr; @@ -56,7 +56,7 @@ class DIGITAL_API digital_pn_correlator_cc : public gr_sync_decimator int d_len; float d_pn; - gri_glfsr *d_reference; + digital_impl_glfsr *d_reference; protected: digital_pn_correlator_cc(int degree, int mask, int seed); diff --git a/gr-digital/lib/digital_constellation.cc b/gr-digital/lib/digital_constellation.cc index d9a53c4930..383c73c30d 100644 --- a/gr-digital/lib/digital_constellation.cc +++ b/gr-digital/lib/digital_constellation.cc @@ -466,8 +466,8 @@ digital_make_constellation_dqpsk() digital_constellation_dqpsk::digital_constellation_dqpsk () { // This constellation is not gray coded, which allows - // us to use differential encodings (through gr_diff_encode and - // gr_diff_decode) on the symbols. + // us to use differential encodings (through digital_diff_encode and + // digital_diff_decode) on the symbols. d_constellation.resize(4); d_constellation[0] = gr_complex(+SQRT_TWO, +SQRT_TWO); d_constellation[1] = gr_complex(-SQRT_TWO, +SQRT_TWO); diff --git a/gr-digital/lib/digital_glfsr_source_b.cc b/gr-digital/lib/digital_glfsr_source_b.cc index e557e475a8..63a5ffdb0a 100644 --- a/gr-digital/lib/digital_glfsr_source_b.cc +++ b/gr-digital/lib/digital_glfsr_source_b.cc @@ -26,7 +26,7 @@ #endif #include <digital_glfsr_source_b.h> -#include <gri_glfsr.h> +#include <digital_impl_glfsr.h> #include <gr_io_signature.h> #include <stdexcept> @@ -50,8 +50,8 @@ digital_glfsr_source_b::digital_glfsr_source_b(int degree, bool repeat, d_length = (unsigned int)((1ULL << degree)-1); if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); + mask = digital_impl_glfsr::glfsr_mask(degree); + d_glfsr = new digital_impl_glfsr(mask, seed); } digital_glfsr_source_b::~digital_glfsr_source_b() diff --git a/gr-digital/lib/digital_glfsr_source_f.cc b/gr-digital/lib/digital_glfsr_source_f.cc index 5a7736ef8d..6ae84d5679 100644 --- a/gr-digital/lib/digital_glfsr_source_f.cc +++ b/gr-digital/lib/digital_glfsr_source_f.cc @@ -26,7 +26,7 @@ #endif #include <digital_glfsr_source_f.h> -#include <gri_glfsr.h> +#include <digital_impl_glfsr.h> #include <gr_io_signature.h> #include <stdexcept> @@ -50,8 +50,8 @@ digital_glfsr_source_f::digital_glfsr_source_f(int degree, bool repeat, d_length = (unsigned int)((1ULL << degree)-1); if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_glfsr = new gri_glfsr(mask, seed); + mask = digital_impl_glfsr::glfsr_mask(degree); + d_glfsr = new digital_impl_glfsr(mask, seed); } digital_glfsr_source_f::~digital_glfsr_source_f() diff --git a/gr-digital/lib/digital_ofdm_insert_preamble.cc b/gr-digital/lib/digital_ofdm_insert_preamble.cc index a46133643d..72b9e82a82 100644 --- a/gr-digital/lib/digital_ofdm_insert_preamble.cc +++ b/gr-digital/lib/digital_ofdm_insert_preamble.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007,2010,2011 Free Software Foundation, Inc. + * Copyright 2007,2010-2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -41,7 +41,7 @@ digital_ofdm_insert_preamble::digital_ofdm_insert_preamble (int fft_length, const std::vector<std::vector<gr_complex> > &preamble) : gr_block("ofdm_insert_preamble", - gr_make_io_signature2(2, 2, + gr_make_io_signature2(1, 2, sizeof(gr_complex)*fft_length, sizeof(char)), gr_make_io_signature2(1, 2, @@ -54,8 +54,8 @@ digital_ofdm_insert_preamble::digital_ofdm_insert_preamble d_pending_flag(0) { // sanity check preamble symbols - for (size_t i = 0; i < d_preamble.size(); i++){ - if (d_preamble[i].size() != (size_t) d_fft_length) + for(size_t i = 0; i < d_preamble.size(); i++) { + if(d_preamble[i].size() != (size_t) d_fft_length) throw std::invalid_argument("digital_ofdm_insert_preamble: invalid length for preamble symbol"); } @@ -67,15 +67,22 @@ digital_ofdm_insert_preamble::~digital_ofdm_insert_preamble() { } +void digital_ofdm_insert_preamble::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = noutput_items; +} + int -digital_ofdm_insert_preamble::general_work (int noutput_items, - gr_vector_int &ninput_items_v, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) +digital_ofdm_insert_preamble::general_work(int noutput_items, + gr_vector_int &ninput_items_v, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { - int ninput_items = std::min(ninput_items_v[0], ninput_items_v[1]); + int ninput_items = ninput_items_v.size()==2?std::min(ninput_items_v[0], ninput_items_v[1]):ninput_items_v[0]; const gr_complex *in_sym = (const gr_complex *) input_items[0]; - const unsigned char *in_flag = (const unsigned char *) input_items[1]; + const unsigned char *in_flag = 0; + if (input_items.size() == 2) + in_flag = (const unsigned char *) input_items[1]; gr_complex *out_sym = (gr_complex *) output_items[0]; unsigned char *out_flag = 0; @@ -97,14 +104,14 @@ digital_ofdm_insert_preamble::general_work (int noutput_items, while (no < noutput_items && ni < ninput_items){ switch(d_state){ case ST_IDLE: - if (in_flag[ni] & 0x1) // this is first symbol of new payload + if (in_flag && in_flag[ni] & 0x1) // this is first symbol of new payload enter_preamble(); else ni++; // eat one input symbol break; case ST_PREAMBLE: - assert(in_flag[ni] & 0x1); + assert(!in_flag || in_flag[ni] & 0x1); if (d_nsymbols_output >= (int) d_preamble.size()){ // we've output all the preamble enter_first_payload(); @@ -133,7 +140,7 @@ digital_ofdm_insert_preamble::general_work (int noutput_items, break; case ST_PAYLOAD: - if (in_flag[ni] & 0x1){ // this is first symbol of a new payload + if (in_flag && in_flag[ni] & 0x1){ // this is first symbol of a new payload enter_preamble(); break; } diff --git a/gr-digital/lib/digital_pn_correlator_cc.cc b/gr-digital/lib/digital_pn_correlator_cc.cc index 43a3ddbd1f..52e06bc2ad 100644 --- a/gr-digital/lib/digital_pn_correlator_cc.cc +++ b/gr-digital/lib/digital_pn_correlator_cc.cc @@ -44,8 +44,8 @@ digital_pn_correlator_cc::digital_pn_correlator_cc(int degree, { d_len = (unsigned int)((1ULL << degree)-1); if (mask == 0) - mask = gri_glfsr::glfsr_mask(degree); - d_reference = new gri_glfsr(mask, seed); + mask = digital_impl_glfsr::glfsr_mask(degree); + d_reference = new digital_impl_glfsr(mask, seed); for (int i = 0; i < d_len; i++) // initialize to last value in sequence d_pn = 2.0*d_reference->next_bit()-1.0; } diff --git a/gr-digital/python/bpsk.py b/gr-digital/python/bpsk.py index 0d8f05c4c1..9f2354003c 100644 --- a/gr-digital/python/bpsk.py +++ b/gr-digital/python/bpsk.py @@ -31,18 +31,11 @@ from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod import digital_swig import modulation_utils -# Default number of points in constellation. -_def_constellation_points = 2 -# Whether differential coding is used. -_def_differential = False - # ///////////////////////////////////////////////////////////////////////////// # BPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def bpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("BPSK can only have 2 constellation points.") +def bpsk_constellation(): return digital_swig.constellation_bpsk() # ///////////////////////////////////////////////////////////////////////////// @@ -51,8 +44,7 @@ def bpsk_constellation(m=_def_constellation_points): class bpsk_mod(generic_mod): - def __init__(self, constellation_points=_def_constellation_points, - differential=False, *args, **kwargs): + def __init__(self, mod_code=None, differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered BPSK modulation. @@ -61,12 +53,12 @@ class bpsk_mod(generic_mod): output is the complex modulated signal at baseband. See generic_mod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for BPSK.') super(bpsk_mod, self).__init__(constellation=constellation, differential=differential, *args, **kwargs) @@ -77,8 +69,7 @@ class bpsk_mod(generic_mod): class bpsk_demod(generic_demod): - def __init__(self, constellation_points=_def_constellation_points, - differential=False, *args, **kwargs): + def __init__(self, mod_code=None, differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered BPSK modulation. @@ -87,12 +78,12 @@ class bpsk_demod(generic_demod): output is the complex modulated signal at baseband. See generic_demod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for BPSK.') super(bpsk_demod, self).__init__(constellation=constellation, differential=differential, *args, **kwargs) @@ -102,19 +93,16 @@ class bpsk_demod(generic_demod): # DBPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def dbpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("DBPSK can only have 2 constellation points.") +def dbpsk_constellation(): return digital_swig.constellation_dbpsk() # ///////////////////////////////////////////////////////////////////////////// # DBPSK modulator # ///////////////////////////////////////////////////////////////////////////// -class dbpsk_mod(generic_mod): +class dbpsk_mod(bpsk_mod): - def __init__(self, constellation_points=_def_constellation_points, - differential=True, *args, **kwargs): + def __init__(self, mod_code=None, *args, **kwargs): """ Hierarchical block for RRC-filtered DBPSK modulation. @@ -123,14 +111,12 @@ class dbpsk_mod(generic_mod): output is the complex modulated signal at baseband. See generic_mod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for DBPSK.') - super(dbpsk_mod, self).__init__(constellation=constellation, - differential=True, + super(dbpsk_mod, self).__init__(differential=True, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -138,10 +124,9 @@ class dbpsk_mod(generic_mod): # # ///////////////////////////////////////////////////////////////////////////// -class dbpsk_demod(generic_demod): +class dbpsk_demod(bpsk_demod): - def __init__(self, constellation_points=_def_constellation_points, - differential=True, *args, **kwargs): + def __init__(self, mod_code=None, *args, **kwargs): """ Hierarchical block for RRC-filtered DBPSK modulation. @@ -150,14 +135,12 @@ class dbpsk_demod(generic_demod): output is the complex modulated signal at baseband. See generic_demod block for list of parameters. + + 'mod_code' argument is not used. + It exists purely to simplify generation of the block in grc. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_bpsk() - if constellation_points != 2: - raise ValueError('Number of constellation points must be 2 for DBPSK.') - super(dbpsk_demod, self).__init__(constellation=constellation, - differential=True, + super(dbpsk_demod, self).__init__(differential=True, *args, **kwargs) # diff --git a/gr-digital/python/cpm.py b/gr-digital/python/cpm.py index 05032336d4..f11832b626 100644 --- a/gr-digital/python/cpm.py +++ b/gr-digital/python/cpm.py @@ -131,7 +131,7 @@ class cpm_mod(gr.hier_block2): # Turn it into symmetric PAM data. - self.pam = gr.chunks_to_symbols_bf(self.sym_alphabet,1) + self.pam = digital_swig.chunks_to_symbols_bf(self.sym_alphabet,1) # Generate pulse (sum of taps = samples_per_symbol/2) if cpm_type == 0: # CPFSK diff --git a/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index a6c4f3445a..105c6fe8ff 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -76,10 +76,10 @@ def add_common_options(parser): class generic_mod(gr.hier_block2): def __init__(self, constellation, - samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, + samples_per_symbol=_def_samples_per_symbol, + pre_diff_code=True, excess_bw=_def_excess_bw, - gray_coded=True, verbose=_def_verbose, log=_def_log): """ @@ -92,10 +92,12 @@ class generic_mod(gr.hier_block2): @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per baud >= 2 @type samples_per_symbol: float + @param differential: whether to use differential encoding + @type differential: boolean + @param pre_diff_code: whether to use apply a pre-differential mapping + @type pre_diff_code: boolean @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float - @param gray_coded: turn gray coding on/off - @type gray_coded: bool @param verbose: Print information about modulator? @type verbose: bool @param log: Log modulation data to files? @@ -110,6 +112,8 @@ class generic_mod(gr.hier_block2): self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._differential = differential + # Only apply a predifferential coding if the constellation also supports it. + self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code() if self._samples_per_symbol < 2: raise TypeError, ("sbp must be >= 2, is %f" % self._samples_per_symbol) @@ -120,7 +124,7 @@ class generic_mod(gr.hier_block2): self.bytes2chunks = \ gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) - if gray_coded == True: + if self.pre_diff_code: self.symbol_mapper = digital.map_bb(self._constellation.pre_diff_code()) if differential: @@ -142,7 +146,7 @@ class generic_mod(gr.hier_block2): # Connect blocks = [self, self.bytes2chunks] - if gray_coded == True: + if self.pre_diff_code: blocks.append(self.symbol_mapper) if differential: blocks.append(self.diffenc) @@ -186,7 +190,7 @@ class generic_mod(gr.hier_block2): print "Modulation logging turned on." self.connect(self.bytes2chunks, gr.file_sink(gr.sizeof_char, "tx_bytes2chunks.8b")) - if self._constellation.apply_pre_diff_code(): + if self.pre_diff_code: self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "tx_symbol_mapper.8b")) if self._differential: @@ -208,10 +212,10 @@ class generic_mod(gr.hier_block2): class generic_demod(gr.hier_block2): def __init__(self, constellation, - samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, + samples_per_symbol=_def_samples_per_symbol, + pre_diff_code=True, excess_bw=_def_excess_bw, - gray_coded=True, freq_bw=_def_freq_bw, timing_bw=_def_timing_bw, phase_bw=_def_phase_bw, @@ -227,10 +231,12 @@ class generic_demod(gr.hier_block2): @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per symbol >= 2 @type samples_per_symbol: float + @param differential: whether to use differential encoding + @type differential: boolean + @param pre_diff_code: whether to use apply a pre-differential mapping + @type pre_diff_code: boolean @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float - @param gray_coded: turn gray coding on/off - @type gray_coded: bool @param freq_bw: loop filter lock-in bandwidth @type freq_bw: float @param timing_bw: timing recovery loop lock-in bandwidth @@ -259,6 +265,9 @@ class generic_demod(gr.hier_block2): if self._samples_per_symbol < 2: raise TypeError, ("sbp must be >= 2, is %d" % self._samples_per_symbol) + # Only apply a predifferential coding if the constellation also supports it. + self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code() + arity = pow(2,self.bits_per_symbol()) nfilts = 32 @@ -289,7 +298,7 @@ class generic_demod(gr.hier_block2): if differential: self.diffdec = digital.diff_decoder_bb(arity) - if gray_coded: + if self.pre_diff_code: self.symbol_mapper = digital.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) @@ -307,7 +316,7 @@ class generic_demod(gr.hier_block2): self.time_recov, self.receiver] if differential: blocks.append(self.diffdec) - if self._constellation.apply_pre_diff_code(): + if self.pre_diff_code: blocks.append(self.symbol_mapper) blocks += [self.unpack, self] self.connect(*blocks) @@ -357,7 +366,7 @@ class generic_demod(gr.hier_block2): if self._differential: self.connect(self.diffdec, gr.file_sink(gr.sizeof_char, "rx_diffdec.8b")) - if self._constellation.apply_pre_diff_code(): + if self.pre_diff_code: self.connect(self.symbol_mapper, gr.file_sink(gr.sizeof_char, "rx_symbol_mapper.8b")) self.connect(self.unpack, diff --git a/gr-digital/python/pkt.py b/gr-digital/python/pkt.py index 8650bdbb02..09254a7caa 100644 --- a/gr-digital/python/pkt.py +++ b/gr-digital/python/pkt.py @@ -143,7 +143,7 @@ class demod_pkts(gr.hier_block2): self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY self.correlator = digital_swig.correlate_access_code_bb(access_code, threshold) - self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + self.framer_sink = digital.framer_sink_1(self._rcvd_pktq) self.connect(self, self._demodulator, self.correlator, self.framer_sink) self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) diff --git a/gr-digital/python/psk.py b/gr-digital/python/psk.py index 58f6787f0c..4b35447278 100644 --- a/gr-digital/python/psk.py +++ b/gr-digital/python/psk.py @@ -35,17 +35,23 @@ from generic_mod_demod import generic_mod, generic_demod _def_constellation_points = 4 # The default encoding (e.g. gray-code, set-partition) _def_mod_code = mod_codes.GRAY_CODE +# Default use of differential encoding +_def_differential = True -def create_encodings(mod_code, arity): +def create_encodings(mod_code, arity, differential): post_diff_code = None if mod_code not in mod_codes.codes: raise ValueError('That modulation code does not exist.') if mod_code == mod_codes.GRAY_CODE: - pre_diff_code = gray_code.gray_code(arity) - elif mod_code == mod_codes.SET_PARTITION_CODE: - pre_diff_code = set_partition_code.set_partition_code(arity) + if differential: + pre_diff_code = gray_code.gray_code(arity) + post_diff_code = None + else: + pre_diff_code = [] + post_diff_code = gray_code.gray_code(arity) elif mod_code == mod_codes.NO_CODE: pre_diff_code = [] + post_diff_code = None else: raise ValueError('That modulation code is not implemented for this constellation.') return (pre_diff_code, post_diff_code) @@ -54,7 +60,8 @@ def create_encodings(mod_code, arity): # PSK constellation # ///////////////////////////////////////////////////////////////////////////// -def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code): +def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code, + differential=_def_differential): """ Creates a PSK constellation object. """ @@ -62,7 +69,7 @@ def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code): if (k != int(k)): raise StandardError('Number of constellation points must be a power of two.') points = [exp(2*pi*(0+1j)*i/m) for i in range(0,m)] - pre_diff_code, post_diff_code = create_encodings(mod_code, m) + pre_diff_code, post_diff_code = create_encodings(mod_code, m, differential) if post_diff_code is not None: inverse_post_diff_code = mod_codes.invert_code(post_diff_code) points = [points[x] for x in inverse_post_diff_code] @@ -77,6 +84,7 @@ class psk_mod(generic_mod): def __init__(self, constellation_points=_def_constellation_points, mod_code=_def_mod_code, + differential=_def_differential, *args, **kwargs): """ @@ -88,8 +96,8 @@ class psk_mod(generic_mod): See generic_mod block for list of parameters. """ - constellation = psk_constellation(constellation_points, mod_code) - super(psk_mod, self).__init__(constellation, *args, **kwargs) + constellation = psk_constellation(constellation_points, mod_code, differential) + super(psk_mod, self).__init__(constellation, differential, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// # PSK demodulator @@ -100,6 +108,7 @@ class psk_demod(generic_demod): def __init__(self, constellation_points=_def_constellation_points, mod_code=_def_mod_code, + differential=_def_differential, *args, **kwargs): """ @@ -111,8 +120,8 @@ class psk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation = psk_constellation(constellation_points, mod_code) - super(psk_demod, self).__init__(constellation, *args, **kwargs) + constellation = psk_constellation(constellation_points, mod_code, differential) + super(psk_demod, self).__init__(constellation, differential, *args, **kwargs) # # Add these to the mod/demod registry diff --git a/gr-digital/python/qa_constellation.py b/gr-digital/python/qa_constellation.py index b17d2a0fcb..e0b5b3888e 100755 --- a/gr-digital/python/qa_constellation.py +++ b/gr-digital/python/qa_constellation.py @@ -67,8 +67,24 @@ def threed_constell(): tested_constellation_info = ( (psk.psk_constellation, {'m': (2, 4, 8, 16, 32, 64), - 'mod_code': tested_mod_codes, }, + 'mod_code': tested_mod_codes, + 'differential': (True,)}, True, None), + (psk.psk_constellation, + {'m': (2, 4, 8, 16, 32, 64), + 'mod_code': tested_mod_codes, + 'differential': (False,)}, + False, None), + (qam.qam_constellation, + {'constellation_points': (4, 16, 64), + 'mod_code': tested_mod_codes, + 'differential': (True,)}, + True, None), + (qam.qam_constellation, + {'constellation_points': (4, 16, 64), + 'mod_code': tested_mod_codes, + 'differential': (False,)}, + False, None), (digital_swig.constellation_bpsk, {}, True, None), (digital_swig.constellation_qpsk, {}, False, None), (digital_swig.constellation_dqpsk, {}, True, None), @@ -167,13 +183,13 @@ class mod_demod(gr.hier_block2): # Apply any pre-differential coding # Gray-coding is done here if we're also using differential coding. if self.constellation.apply_pre_diff_code(): - self.blocks.append(gr.map_bb(self.constellation.pre_diff_code())) + self.blocks.append(digital_swig.map_bb(self.constellation.pre_diff_code())) # Differential encoding. if self.differential: - self.blocks.append(gr.diff_encoder_bb(arity)) + self.blocks.append(digital_swig.diff_encoder_bb(arity)) # Convert to constellation symbols. - self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), - self.constellation.dimensionality())) + self.blocks.append(digital_swig.chunks_to_symbols_bc(self.constellation.points(), + self.constellation.dimensionality())) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: @@ -184,10 +200,10 @@ class mod_demod(gr.hier_block2): self.blocks.append(digital_swig.constellation_decoder_cb(self.constellation.base())) # Differential decoding. if self.differential: - self.blocks.append(gr.diff_decoder_bb(arity)) + self.blocks.append(digital_swig.diff_decoder_bb(arity)) # Decode any pre-differential coding. if self.constellation.apply_pre_diff_code(): - self.blocks.append(gr.map_bb( + self.blocks.append(digital_swig.map_bb( mod_codes.invert_code(self.constellation.pre_diff_code()))) # unpack the k bit vector into a stream of bits self.blocks.append(gr.unpack_k_bits_bb( diff --git a/gr-digital/python/qa_constellation_receiver.py b/gr-digital/python/qa_constellation_receiver.py index 2d25433b92..8c2d2da0c5 100755 --- a/gr-digital/python/qa_constellation_receiver.py +++ b/gr-digital/python/qa_constellation_receiver.py @@ -85,11 +85,16 @@ class test_constellation_receiver (gr_unittest.TestCase): # That is not implemented since the receiver has no way of # knowing where the beginning of a symbol is. # It also doesn't work for non-differential modulation. - if constellation.dimensionality() != 1 or not differential: + if constellation.dimensionality() != 1: continue data_length = DATA_LENGTH * constellation.bits_per_symbol() + if differential: + freq_offset=True + else: + freq_offset=False tb = rec_test_tb(constellation, differential, - src_data=self.src_data[:data_length]) + src_data=self.src_data[:data_length], + freq_offset=freq_offset) tb.run() data = tb.dst.data() d1 = tb.src_data[:int(len(tb.src_data)*self.ignore_fraction)] @@ -105,12 +110,14 @@ class rec_test_tb (gr.top_block): and generic demodulation. """ def __init__(self, constellation, differential, - data_length=None, src_data=None): + data_length=None, src_data=None, freq_offset=True): """ - constellation -- a constellation object - differential -- whether differential encoding is used - data_length -- the number of bits of data to use - src_data -- a list of the bits to use + Args: + constellation: a constellation object + differential: whether differential encoding is used + data_length: the number of bits of data to use + src_data: a list of the bits to use + freq_offset: whether to use a frequency offset in the channel """ super(rec_test_tb, self).__init__() # Transmission Blocks @@ -122,11 +129,18 @@ class rec_test_tb (gr.top_block): src = gr.vector_source_b(self.src_data) mod = generic_mod(constellation, differential=differential) # Channel - channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET) + if freq_offset: + channel = gr.channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET) + else: + channel = gr.channel_model(NOISE_VOLTAGE, 0, TIMING_OFFSET) # Receiver Blocks - demod = generic_demod(constellation, differential=differential, - freq_bw=FREQ_BW, - phase_bw=PHASE_BW) + if freq_offset: + demod = generic_demod(constellation, differential=differential, + freq_bw=FREQ_BW, + phase_bw=PHASE_BW) + else: + demod = generic_demod(constellation, differential=differential, + freq_bw=0, phase_bw=0) self.dst = gr.vector_sink_b() self.connect(src, packer, mod, channel, demod, self.dst) diff --git a/gr-digital/python/qa_glfsr_source.py b/gr-digital/python/qa_glfsr_source.py index 157520d7f8..7d02037335 100755 --- a/gr-digital/python/qa_glfsr_source.py +++ b/gr-digital/python/qa_glfsr_source.py @@ -38,9 +38,9 @@ class test_glfsr_source(gr_unittest.TestCase): def test_001_degree_b(self): self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(0)) + lambda: digital.glfsr_source_b(0)) self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_b(33)) + lambda: digital.glfsr_source_b(33)) def test_002_correlation_b(self): for degree in range(1,11): # Higher degrees take too long to correlate @@ -65,9 +65,9 @@ class test_glfsr_source(gr_unittest.TestCase): def test_004_degree_f(self): self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(0)) + lambda: digital.glfsr_source_f(0)) self.assertRaises(RuntimeError, - lambda: gr.glfsr_source_f(33)) + lambda: digital.glfsr_source_f(33)) def test_005_correlation_f(self): for degree in range(1,11): # Higher degrees take too long to correlate src = digital.glfsr_source_f(degree, False) diff --git a/gr-digital/python/qam.py b/gr-digital/python/qam.py index 5b1f7683b8..0635fda75e 100644 --- a/gr-digital/python/qam.py +++ b/gr-digital/python/qam.py @@ -157,14 +157,20 @@ def qam_constellation(constellation_points=_def_constellation_points, else: raise ValueError("Mod code is not implemented for QAM") if differential: - points = make_differential_constellation(constellation_points, gray_coded) + points = make_differential_constellation(constellation_points, gray_coded=False) else: points = make_non_differential_constellation(constellation_points, gray_coded) side = int(sqrt(constellation_points)) width = 2.0/(side-1) - # No pre-diff code - # Should add one so that we can gray-code the quadrant bits too. - pre_diff_code = [] + # For differential and gray-coded then gray-code the first two + # bits with a pre_diff_code. + # FIXME: It would be good to have a test to make sure that gray-coded constellations + # are really gray-coded. Perhaps by checking on the correlation between bit-errors. + if differential and gray_coded: + m = constellation_points + pre_diff_code = range(0, m/2) + range(3*m/4, m) + range(m/2, 3*m/4) + else: + pre_diff_code = [] constellation = digital_swig.constellation_rect(points, pre_diff_code, 4, side, side, width, width) return constellation diff --git a/gr-digital/python/qpsk.py b/gr-digital/python/qpsk.py index be21fd76f1..2fdeabd40f 100644 --- a/gr-digital/python/qpsk.py +++ b/gr-digital/python/qpsk.py @@ -27,21 +27,20 @@ Demodulation is not included since the generic_mod_demod from gnuradio import gr from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod +from utils import mod_codes import digital_swig import modulation_utils -# Default number of points in constellation. -_def_constellation_points = 4 -# Whether gray coding is used. -_def_gray_coded = True +# The default encoding (e.g. gray-code, set-partition) +_def_mod_code = mod_codes.GRAY_CODE # ///////////////////////////////////////////////////////////////////////////// # QPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def qpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("QPSK can only have 4 constellation points.") +def qpsk_constellation(mod_code=_def_mod_code): + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") return digital_swig.constellation_qpsk() # ///////////////////////////////////////////////////////////////////////////// @@ -50,9 +49,7 @@ def qpsk_constellation(m=_def_constellation_points): class qpsk_mod(generic_mod): - def __init__(self, constellation_points=_def_constellation_points, - gray_coded=_def_gray_coded, - *args, **kwargs): + def __init__(self, mod_code=_def_mod_code, differential=False, *args, **kwargs): """ Hierarchical block for RRC-filtered QPSK modulation. @@ -62,15 +59,21 @@ class qpsk_mod(generic_mod): See generic_mod block for list of parameters. """ - - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_qpsk() - if constellation_points != 4: - raise ValueError("QPSK can only have 4 constellation points.") - if not gray_coded: - raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + + pre_diff_code = True + if not differential: + constellation = digital_swig.constellation_qpsk() + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + else: + constellation = digital_swig.constellation_dqpsk() + if mod_code not in (mod_codes.GRAY_CODE or mod_codes.NO_CODE): + raise ValueError("That mod_code is not supported for DQPSK mod/demod.") + if mod_code == mod_codes.NO_CODE: + pre_diff_code = False + super(qpsk_mod, self).__init__(constellation=constellation, - gray_coded=gray_coded, + pre_diff_code=pre_diff_code, *args, **kwargs) @@ -81,7 +84,7 @@ class qpsk_mod(generic_mod): class qpsk_demod(generic_demod): - def __init__(self, constellation_points=_def_constellation_points, + def __init__(self, mod_code=_def_mod_code, differential=False, *args, **kwargs): """ @@ -93,11 +96,20 @@ class qpsk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_qpsk() - if constellation_points != 4: - raise ValueError('Number of constellation points must be 4 for QPSK.') + pre_diff_code = True + if not differential: + constellation = digital_swig.constellation_qpsk() + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("This QPSK mod/demod works only for gray-coded constellations.") + else: + constellation = digital_swig.constellation_dqpsk() + if mod_code not in (mod_codes.GRAY_CODE or mod_codes.NO_CODE): + raise ValueError("That mod_code is not supported for DQPSK mod/demod.") + if mod_code == mod_codes.NO_CODE: + pre_diff_code = False + super(qpsk_demod, self).__init__(constellation=constellation, + pre_diff_code=pre_diff_code, *args, **kwargs) @@ -106,20 +118,18 @@ class qpsk_demod(generic_demod): # DQPSK constellation # ///////////////////////////////////////////////////////////////////////////// -def dqpsk_constellation(m=_def_constellation_points): - if m != _def_constellation_points: - raise ValueError("DQPSK can only have 4 constellation points.") +def dqpsk_constellation(mod_code=_def_mod_code): + if mod_code != mod_codes.GRAY_CODE: + raise ValueError("The DQPSK constellation is only generated for gray_coding. But it can be used for non-grayed coded modulation if one doesn't use the pre-differential code.") return digital_swig.constellation_dqpsk() # ///////////////////////////////////////////////////////////////////////////// # DQPSK modulator # ///////////////////////////////////////////////////////////////////////////// -class dqpsk_mod(generic_mod): +class dqpsk_mod(qpsk_mod): - def __init__(self, constellation_points=_def_constellation_points, - gray_coded=_def_gray_coded, - differential=True, *args, **kwargs): + def __init__(self, mod_code=_def_mod_code, *args, **kwargs): """ Hierarchical block for RRC-filtered DQPSK modulation. @@ -128,14 +138,7 @@ class dqpsk_mod(generic_mod): See generic_mod block for list of parameters. """ - - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_dqpsk() - if constellation_points != 4: - raise ValueError('Number of constellation points must be 4 for DQPSK.') - super(dqpsk_mod, self).__init__(constellation=constellation, - gray_coded=gray_coded, - differential=True, + super(dqpsk_mod, self).__init__(mod_code, differential=True, *args, **kwargs) # ///////////////////////////////////////////////////////////////////////////// @@ -143,10 +146,9 @@ class dqpsk_mod(generic_mod): # # ///////////////////////////////////////////////////////////////////////////// -class dqpsk_demod(generic_demod): +class dqpsk_demod(qpsk_demod): - def __init__(self, constellation_points=_def_constellation_points, - differential=True, *args, **kwargs): + def __init__(self, mod_code=_def_mod_code, *args, **kwargs): """ Hierarchical block for RRC-filtered DQPSK modulation. @@ -156,12 +158,7 @@ class dqpsk_demod(generic_demod): See generic_demod block for list of parameters. """ - constellation_points = _def_constellation_points - constellation = digital_swig.constellation_dqpsk() - if constellation_points != 4: - raise ValueError('Number of constellation points must be 4 for DQPSK.') - super(dqpsk_demod, self).__init__(constellation=constellation, - differential=True, + super(dqpsk_demod, self).__init__(mod_code, differential=True, *args, **kwargs) # diff --git a/gr-digital/swig/digital_ofdm_insert_preamble.i b/gr-digital/swig/digital_ofdm_insert_preamble.i index 5f7b163698..0273c7fa75 100644 --- a/gr-digital/swig/digital_ofdm_insert_preamble.i +++ b/gr-digital/swig/digital_ofdm_insert_preamble.i @@ -32,4 +32,6 @@ class digital_ofdm_insert_preamble : public gr_block protected: digital_ofdm_insert_preamble(int fft_length, const std::vector<std::vector<gr_complex> > &preamble); + public: + void enter_preamble(); }; diff --git a/gr-fcd/grc/fcd_source_c.xml b/gr-fcd/grc/fcd_source_c.xml index 1b83cba7fb..f1726f88f2 100644 --- a/gr-fcd/grc/fcd_source_c.xml +++ b/gr-fcd/grc/fcd_source_c.xml @@ -12,7 +12,7 @@ self.$(id).set_lna_gain($lna) #if $mixer() != +12.0 self.$(id).set_mixer_gain($mixer) #end if -#if $ppm() != 115 +#if $ppm() != -120 self.$(id).set_freq_corr($ppm) #end if #if ($dci() != 0.0) or ($dcq() != 0.0) diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h index 5cc2e21e81..e3fd3f278a 100644 --- a/gr-fft/include/fft/fft.h +++ b/gr-fft/include/fft/fft.h @@ -37,15 +37,15 @@ namespace gr { /*! \brief Helper function for allocating complex fft buffers */ - gr_complex* malloc_complex(int size); + FFT_API gr_complex* malloc_complex(int size); /*! \brief Helper function for allocating float fft buffers */ - float* malloc_float(int size); + FFT_API float* malloc_float(int size); /*! \brief Helper function for freeing fft buffers */ - void free(void *b); + FFT_API void free(void *b); /*! * \brief Export reference to planner mutex for those apps that diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt index e2f17a1830..ea1248fbac 100644 --- a/gr-fft/lib/CMakeLists.txt +++ b/gr-fft/lib/CMakeLists.txt @@ -21,19 +21,16 @@ # Setup the include and linker paths ######################################################################## include_directories( - ${GNURADIO_CORE_INCLUDE_DIRS} - ${GR_FFT_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_FFT_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} ) -include_directories(${FFT_INCLUDE_DIRS}) link_directories(${FFT_LIBRARY_DIRS}) - -include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) - -include_directories(${FFTW3F_INCLUDE_DIRS}) link_directories(${FFTW3F_LIBRARY_DIRS}) ######################################################################## diff --git a/gr-fft/swig/CMakeLists.txt b/gr-fft/swig/CMakeLists.txt index 63f5dfb0e2..7ea41f220e 100644 --- a/gr-fft/swig/CMakeLists.txt +++ b/gr-fft/swig/CMakeLists.txt @@ -30,7 +30,7 @@ set(GR_SWIG_INCLUDE_DIRS ) set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i) -set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) +set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/fft) set(GR_SWIG_LIBRARIES gnuradio-fft) diff --git a/gr-filter/CMakeLists.txt b/gr-filter/CMakeLists.txt new file mode 100644 index 0000000000..b77a3d9d44 --- /dev/null +++ b/gr-filter/CMakeLists.txt @@ -0,0 +1,113 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup dependencies +######################################################################## +include(GrBoost) + +######################################################################## +# Register component +######################################################################## +include(GrComponent) + +GR_REGISTER_COMPONENT("gr-filter" ENABLE_GR_FILTER + ENABLE_GRUEL + ENABLE_VOLK + Boost_FOUND + ENABLE_GR_CORE + ENABLE_GR_FFT +) + +GR_SET_GLOBAL(GR_FILTER_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/lib + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/lib + ${CMAKE_CURRENT_BINARY_DIR}/include +) + +SET(GR_PKG_FILTER_EXAMPLES_DIR ${GR_PKG_DATA_DIR}/examples/filter) + +######################################################################## +# Begin conditional configuration +######################################################################## +if(ENABLE_GR_FILTER) + +######################################################################## +# Setup CPack components +######################################################################## +include(GrPackage) +CPACK_SET(CPACK_COMPONENT_GROUP_FILTER_DESCRIPTION "GNU Radio Filter Blocks") + +CPACK_COMPONENT("filter_runtime" + GROUP "Filter" + DISPLAY_NAME "Runtime" + DESCRIPTION "Runtime" + DEPENDS "core_runtime" +) + +CPACK_COMPONENT("filter_devel" + GROUP "Filter" + DISPLAY_NAME "Development" + DESCRIPTION "C++ headers, package config, import libraries" + DEPENDS "core_devel" +) + +CPACK_COMPONENT("filter_python" + GROUP "Filter" + DISPLAY_NAME "Python" + DESCRIPTION "Python modules for runtime; GRC xml files" + DEPENDS "core_python;filter_runtime" +) + +CPACK_COMPONENT("filter_swig" + GROUP "Filter" + DISPLAY_NAME "SWIG" + DESCRIPTION "SWIG development .i files" + DEPENDS "core_swig;filter_python;filter_devel" +) + +######################################################################## +# Add subdirectories +######################################################################## +add_subdirectory(include/filter) +add_subdirectory(lib) +if(ENABLE_PYTHON) + add_subdirectory(swig) + add_subdirectory(python) + add_subdirectory(grc) +endif(ENABLE_PYTHON) +add_subdirectory(examples) +add_subdirectory(doc) + +######################################################################## +# Create Pkg Config File +######################################################################## +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio-filter.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-filter.pc +@ONLY) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-filter.pc + DESTINATION ${GR_LIBRARY_DIR}/pkgconfig + COMPONENT "filter_devel" +) + +endif(ENABLE_GR_FILTER) diff --git a/gr-filter/doc/CMakeLists.txt b/gr-filter/doc/CMakeLists.txt new file mode 100644 index 0000000000..63447ed2ce --- /dev/null +++ b/gr-filter/doc/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install( + FILES README.filter + DESTINATION ${GR_PKG_DOC_DIR} +) diff --git a/gr-filter/doc/README.filter b/gr-filter/doc/README.filter new file mode 100644 index 0000000000..776acd46c7 --- /dev/null +++ b/gr-filter/doc/README.filter @@ -0,0 +1,13 @@ +This is the gr-filter package. It contains signal processing blocks to +perform filtering operations. + +The Python namespace is in gnuradio.filter, which would be normally +imported as: + + from gnuradio import filter + +See the Doxygen documentation for details about the blocks available +in this package. A quick listing of the details can be found in Python +after importing by using: + + help(filter) diff --git a/gr-filter/doc/filter.dox b/gr-filter/doc/filter.dox new file mode 100644 index 0000000000..fc3b52e91b --- /dev/null +++ b/gr-filter/doc/filter.dox @@ -0,0 +1,27 @@ +/*! \page page_filter filter Signal Processing Blocks + +\section Introduction + +This is the gr-filter package. It contains signal processing blocks to +perform filtering operations. + +The Python namespace is in gnuradio.filter, which would be normally +imported as: + +\code + from gnuradio import filter +\endcode + +See the Doxygen documentation for details about the blocks available +in this package. A quick listing of the details can be found in Python +after importing by using: + +\code + help(filter) +\endcode + +\section Dependencies + +The filter blocks depend on \ref page_fft. + +*/ diff --git a/gr-filter/examples/CMakeLists.txt b/gr-filter/examples/CMakeLists.txt new file mode 100644 index 0000000000..d94e5c16e1 --- /dev/null +++ b/gr-filter/examples/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +include(GrPython) + +# Base stuff +GR_PYTHON_INSTALL(PROGRAMS + channelize.py + chirp_channelize.py + decimate.py + fft_filter_ccc.py + fir_filter_ccc.py + fir_filter_fff.py + fmtest.py + interpolate.py + reconstruction.py + resampler.py + resampler_demo.grc + synth_filter.py + synth_to_chan.py + DESTINATION ${GR_PKG_FILTER_EXAMPLES_DIR} + COMPONENT "filter_python" +) diff --git a/gr-filter/examples/channelize.py b/gr-filter/examples/channelize.py new file mode 100755 index 0000000000..1f784d9b06 --- /dev/null +++ b/gr-filter/examples/channelize.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# +# Copyright 2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, blks2 +from gnuradio import filter +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 2000000 # number of samples to use + self._fs = 1000 # initial sampling rate + self._M = M = 9 # Number of channels to channelize + self._ifs = M*self._fs # initial sampling rate + + # Create a set of taps for the PFB channelizer + self._taps = filter.firdes.low_pass_2(1, self._ifs, 475.50, 50, + attenuation_dB=100, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) + print "Number of taps: ", len(self._taps) + print "Number of channels: ", self._M + print "Taps per channel: ", tpc + + # Create a set of signals at different frequencies + # freqs lists the frequencies of the signals that get stored + # in the list "signals", which then get summed together + self.signals = list() + self.add = gr.add_cc() + freqs = [-70, -50, -30, -10, 10, 20, 40, 60, 80] + for i in xrange(len(freqs)): + f = freqs[i] + (M/2-M+i+1)*self._fs + self.signals.append(gr.sig_source_c(self._ifs, gr.GR_SIN_WAVE, f, 1)) + self.connect(self.signals[i], (self.add,i)) + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct the channelizer filter + self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps, 1) + + # Construct a vector sink for the input signal to the channelizer + self.snk_i = gr.vector_sink_c() + + # Connect the blocks + self.connect(self.add, self.head, self.pfb) + self.connect(self.add, self.snk_i) + + # Use this to play with the channel mapping + #self.pfb.set_channel_map([5,6,7,8,0,1,2,3,4]) + + # Create a vector sink for each of M output channels of the filter and connect it + self.snks = list() + for i in xrange(self._M): + self.snks.append(gr.vector_sink_c()) + self.connect((self.pfb, i), self.snks[i]) + + +def main(): + tstart = time.time() + + tb = pfb_top_block() + tb.run() + + tend = time.time() + print "Run time: %f" % (tend - tstart) + + if 1: + fig_in = pylab.figure(1, figsize=(16,9), facecolor="w") + fig1 = pylab.figure(2, figsize=(16,9), facecolor="w") + fig2 = pylab.figure(3, figsize=(16,9), facecolor="w") + + Ns = 1000 + Ne = 10000 + + fftlen = 8192 + winfunc = scipy.blackman + fs = tb._ifs + + # Plot the input signal on its own figure + d = tb.snk_i.data()[Ns:Ne] + spin_f = fig_in.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(X)) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + pin_f = spin_f.plot(f_in, X_in, "b") + spin_f.set_xlim([min(f_in), max(f_in)+1]) + spin_f.set_ylim([-200.0, 50.0]) + + spin_f.set_title("Input Signal", weight="bold") + spin_f.set_xlabel("Frequency (Hz)") + spin_f.set_ylabel("Power (dBW)") + + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + spin_t = fig_in.add_subplot(2, 1, 2) + pin_t = spin_t.plot(t_in, x_in.real, "b") + pin_t = spin_t.plot(t_in, x_in.imag, "r") + + spin_t.set_xlabel("Time (s)") + spin_t.set_ylabel("Amplitude") + + Ncols = int(scipy.floor(scipy.sqrt(tb._M))) + Nrows = int(scipy.floor(tb._M / Ncols)) + if(tb._M % Ncols != 0): + Nrows += 1 + + # Plot each of the channels outputs. Frequencies on Figure 2 and + # time signals on Figure 3 + fs_o = tb._fs + Ts_o = 1.0/fs_o + Tmax_o = len(d)*Ts_o + for i in xrange(len(tb.snks)): + # remove issues with the transients at the beginning + # also remove some corruption at the end of the stream + # this is a bug, probably due to the corner cases + d = tb.snks[i].data()[Ns:Ne] + + sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i) + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(X)) + f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + p2_f = sp1_f.plot(f_o, X_o, "b") + sp1_f.set_xlim([min(f_o), max(f_o)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + sp1_f.set_title(("Channel %d" % i), weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + x_o = scipy.array(d) + t_o = scipy.arange(0, Tmax_o, Ts_o) + sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i) + p2_o = sp2_o.plot(t_o, x_o.real, "b") + p2_o = sp2_o.plot(t_o, x_o.imag, "r") + sp2_o.set_xlim([min(t_o), max(t_o)+1]) + sp2_o.set_ylim([-2, 2]) + + sp2_o.set_title(("Channel %d" % i), weight="bold") + sp2_o.set_xlabel("Time (s)") + sp2_o.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/chirp_channelize.py b/gr-filter/examples/chirp_channelize.py new file mode 100755 index 0000000000..3638c55d1a --- /dev/null +++ b/gr-filter/examples/chirp_channelize.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python +# +# Copyright 2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, blks2 +from gnuradio import filter +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 200000 # number of samples to use + self._fs = 9000 # initial sampling rate + self._M = 9 # Number of channels to channelize + + # Create a set of taps for the PFB channelizer + self._taps = filter.firdes.low_pass_2(1, self._fs, 500, 20, + attenuation_dB=10, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) + print "Number of taps: ", len(self._taps) + print "Number of channels: ", self._M + print "Taps per channel: ", tpc + + repeated = True + if(repeated): + self.vco_input = gr.sig_source_f(self._fs, gr.GR_SIN_WAVE, 0.25, 110) + else: + amp = 100 + data = scipy.arange(0, amp, amp/float(self._N)) + self.vco_input = gr.vector_source_f(data, False) + + # Build a VCO controlled by either the sinusoid or single chirp tone + # Then convert this to a complex signal + self.vco = gr.vco_f(self._fs, 225, 1) + self.f2c = gr.float_to_complex() + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct the channelizer filter + self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps) + + # Construct a vector sink for the input signal to the channelizer + self.snk_i = gr.vector_sink_c() + + # Connect the blocks + self.connect(self.vco_input, self.vco, self.f2c) + self.connect(self.f2c, self.head, self.pfb) + self.connect(self.f2c, self.snk_i) + + # Create a vector sink for each of M output channels of the filter and connect it + self.snks = list() + for i in xrange(self._M): + self.snks.append(gr.vector_sink_c()) + self.connect((self.pfb, i), self.snks[i]) + + +def main(): + tstart = time.time() + + tb = pfb_top_block() + tb.run() + + tend = time.time() + print "Run time: %f" % (tend - tstart) + + if 1: + fig_in = pylab.figure(1, figsize=(16,9), facecolor="w") + fig1 = pylab.figure(2, figsize=(16,9), facecolor="w") + fig2 = pylab.figure(3, figsize=(16,9), facecolor="w") + fig3 = pylab.figure(4, figsize=(16,9), facecolor="w") + + Ns = 650 + Ne = 20000 + + fftlen = 8192 + winfunc = scipy.blackman + fs = tb._fs + + # Plot the input signal on its own figure + d = tb.snk_i.data()[Ns:Ne] + spin_f = fig_in.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + pin_f = spin_f.plot(f_in, X_in, "b") + spin_f.set_xlim([min(f_in), max(f_in)+1]) + spin_f.set_ylim([-200.0, 50.0]) + + spin_f.set_title("Input Signal", weight="bold") + spin_f.set_xlabel("Frequency (Hz)") + spin_f.set_ylabel("Power (dBW)") + + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + spin_t = fig_in.add_subplot(2, 1, 2) + pin_t = spin_t.plot(t_in, x_in.real, "b") + pin_t = spin_t.plot(t_in, x_in.imag, "r") + + spin_t.set_xlabel("Time (s)") + spin_t.set_ylabel("Amplitude") + + Ncols = int(scipy.floor(scipy.sqrt(tb._M))) + Nrows = int(scipy.floor(tb._M / Ncols)) + if(tb._M % Ncols != 0): + Nrows += 1 + + # Plot each of the channels outputs. Frequencies on Figure 2 and + # time signals on Figure 3 + fs_o = tb._fs / tb._M + Ts_o = 1.0/fs_o + Tmax_o = len(d)*Ts_o + for i in xrange(len(tb.snks)): + # remove issues with the transients at the beginning + # also remove some corruption at the end of the stream + # this is a bug, probably due to the corner cases + d = tb.snks[i].data()[Ns:Ne] + + sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i) + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(X)) + f_o = freq + p2_f = sp1_f.plot(f_o, X_o, "b") + sp1_f.set_xlim([min(f_o), max(f_o)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + sp1_f.set_title(("Channel %d" % i), weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + x_o = scipy.array(d) + t_o = scipy.arange(0, Tmax_o, Ts_o) + sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i) + p2_o = sp2_o.plot(t_o, x_o.real, "b") + p2_o = sp2_o.plot(t_o, x_o.imag, "r") + sp2_o.set_xlim([min(t_o), max(t_o)+1]) + sp2_o.set_ylim([-2, 2]) + + sp2_o.set_title(("Channel %d" % i), weight="bold") + sp2_o.set_xlabel("Time (s)") + sp2_o.set_ylabel("Amplitude") + + + sp3 = fig3.add_subplot(1,1,1) + p3 = sp3.plot(t_o, x_o.real) + sp3.set_xlim([min(t_o), max(t_o)+1]) + sp3.set_ylim([-2, 2]) + + sp3.set_title("All Channels") + sp3.set_xlabel("Time (s)") + sp3.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/decimate.py b/gr-filter/examples/decimate.py new file mode 100755 index 0000000000..7f1f03d8f2 --- /dev/null +++ b/gr-filter/examples/decimate.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# +# Copyright 2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio import filter +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 10000000 # number of samples to use + self._fs = 10000 # initial sampling rate + self._decim = 20 # Decimation rate + + # Generate the prototype filter taps for the decimators with a 200 Hz bandwidth + self._taps = filter.firdes.low_pass_2(1, self._fs, + 200, 150, + attenuation_dB=120, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._decim)) + print "Number of taps: ", len(self._taps) + print "Number of filters: ", self._decim + print "Taps per channel: ", tpc + + # Build the input signal source + # We create a list of freqs, and a sine wave is generated and added to the source + # for each one of these frequencies. + self.signals = list() + self.add = gr.add_cc() + freqs = [10, 20, 2040] + for i in xrange(len(freqs)): + self.signals.append(gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freqs[i], 1)) + self.connect(self.signals[i], (self.add,i)) + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct a PFB decimator filter + self.pfb = filter.pfb.decimator_ccf(self._decim, self._taps, 0) + + # Construct a standard FIR decimating filter + self.dec = filter.fir_filter_ccf(self._decim, self._taps) + + self.snk_i = gr.vector_sink_c() + + # Connect the blocks + self.connect(self.add, self.head, self.pfb) + self.connect(self.add, self.snk_i) + + # Create the sink for the decimated siganl + self.snk = gr.vector_sink_c() + self.connect(self.pfb, self.snk) + + +def main(): + tb = pfb_top_block() + + tstart = time.time() + tb.run() + tend = time.time() + print "Run time: %f" % (tend - tstart) + + if 1: + fig1 = pylab.figure(1, figsize=(16,9)) + fig2 = pylab.figure(2, figsize=(16,9)) + + Ns = 10000 + Ne = 10000 + + fftlen = 8192 + winfunc = scipy.blackman + fs = tb._fs + + # Plot the input to the decimator + + d = tb.snk_i.data()[Ns:Ns+Ne] + sp1_f = fig1.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + p1_f = sp1_f.plot(f_in, X_in, "b") + sp1_f.set_xlim([min(f_in), max(f_in)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + sp1_f.set_title("Input Signal", weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + sp1_t = fig1.add_subplot(2, 1, 2) + p1_t = sp1_t.plot(t_in, x_in.real, "b") + p1_t = sp1_t.plot(t_in, x_in.imag, "r") + sp1_t.set_ylim([-tb._decim*1.1, tb._decim*1.1]) + + sp1_t.set_xlabel("Time (s)") + sp1_t.set_ylabel("Amplitude") + + + # Plot the output of the decimator + fs_o = tb._fs / tb._decim + + sp2_f = fig2.add_subplot(2, 1, 1) + d = tb.snk.data()[Ns:Ns+Ne] + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + p2_f = sp2_f.plot(f_o, X_o, "b") + sp2_f.set_xlim([min(f_o), max(f_o)+1]) + sp2_f.set_ylim([-200.0, 50.0]) + + sp2_f.set_title("PFB Decimated Signal", weight="bold") + sp2_f.set_xlabel("Frequency (Hz)") + sp2_f.set_ylabel("Power (dBW)") + + + Ts_o = 1.0/fs_o + Tmax_o = len(d)*Ts_o + + x_o = scipy.array(d) + t_o = scipy.arange(0, Tmax_o, Ts_o) + sp2_t = fig2.add_subplot(2, 1, 2) + p2_t = sp2_t.plot(t_o, x_o.real, "b-o") + p2_t = sp2_t.plot(t_o, x_o.imag, "r-o") + sp2_t.set_ylim([-2.5, 2.5]) + + sp2_t.set_xlabel("Time (s)") + sp2_t.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/fft_filter_ccc.py b/gr-filter/examples/fft_filter_ccc.py new file mode 100755 index 0000000000..45e241a6f6 --- /dev/null +++ b/gr-filter/examples/fft_filter_ccc.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python + +from gnuradio import gr, filter +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +try: + import scipy +except ImportError: + print "Error: could not import scipy (http://www.scipy.org/)" + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + sys.exit(1) + +class example_fft_filter_ccc(gr.top_block): + def __init__(self, N, fs, bw0, bw1, tw, atten, D): + gr.top_block.__init__(self) + + self._nsamps = N + self._fs = fs + self._bw0 = bw0 + self._bw1 = bw1 + self._tw = tw + self._at = atten + self._decim = D + taps = filter.firdes.complex_band_pass_2(1, self._fs, + self._bw0, self._bw1, + self._tw, self._at) + print "Num. Taps: ", len(taps) + + self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1) + self.head = gr.head(gr.sizeof_gr_complex, self._nsamps) + + self.filt0 = filter.fft_filter_ccc(self._decim, taps) + + self.vsnk_src = gr.vector_sink_c() + self.vsnk_out = gr.vector_sink_c() + + self.connect(self.src, self.head, self.vsnk_src) + self.connect(self.head, self.filt0, self.vsnk_out) + +def main(): + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=10000, + help="Number of samples to process [default=%default]") + parser.add_option("-s", "--samplerate", type="eng_float", default=8000, + help="System sample rate [default=%default]") + parser.add_option("-S", "--start-pass", type="eng_float", default=1000, + help="Start of Passband [default=%default]") + parser.add_option("-E", "--end-pass", type="eng_float", default=2000, + help="End of Passband [default=%default]") + parser.add_option("-T", "--transition", type="eng_float", default=100, + help="Transition band [default=%default]") + parser.add_option("-A", "--attenuation", type="eng_float", default=80, + help="Stopband attenuation [default=%default]") + parser.add_option("-D", "--decimation", type="int", default=1, + help="Decmation factor [default=%default]") + (options, args) = parser.parse_args () + + put = example_fft_filter_ccc(options.nsamples, + options.samplerate, + options.start_pass, + options.end_pass, + options.transition, + options.attenuation, + options.decimation) + put.run() + + data_src = scipy.array(put.vsnk_src.data()) + data_snk = scipy.array(put.vsnk_out.data()) + + # Plot the signals PSDs + nfft = 1024 + f1 = pylab.figure(1, figsize=(12,10)) + s1 = f1.add_subplot(1,1,1) + s1.psd(data_src, NFFT=nfft, noverlap=nfft/4, + Fs=options.samplerate) + s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4, + Fs=options.samplerate) + + f2 = pylab.figure(2, figsize=(12,10)) + s2 = f2.add_subplot(1,1,1) + s2.plot(data_src) + s2.plot(data_snk.real, 'g') + + pylab.show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/fir_filter_ccc.py b/gr-filter/examples/fir_filter_ccc.py new file mode 100755 index 0000000000..baa05eeb7c --- /dev/null +++ b/gr-filter/examples/fir_filter_ccc.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +from gnuradio import gr, filter +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +try: + import scipy +except ImportError: + print "Error: could not import scipy (http://www.scipy.org/)" + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + sys.exit(1) + +class example_fir_filter_ccc(gr.top_block): + def __init__(self, N, fs, bw, tw, atten, D): + gr.top_block.__init__(self) + + self._nsamps = N + self._fs = fs + self._bw = bw + self._tw = tw + self._at = atten + self._decim = D + taps = filter.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at) + print "Num. Taps: ", len(taps) + + self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1) + self.head = gr.head(gr.sizeof_gr_complex, self._nsamps) + + self.filt0 = filter.fir_filter_ccc(self._decim, taps) + + self.vsnk_src = gr.vector_sink_c() + self.vsnk_out = gr.vector_sink_c() + + self.connect(self.src, self.head, self.vsnk_src) + self.connect(self.head, self.filt0, self.vsnk_out) + +def main(): + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=10000, + help="Number of samples to process [default=%default]") + parser.add_option("-s", "--samplerate", type="eng_float", default=8000, + help="System sample rate [default=%default]") + parser.add_option("-B", "--bandwidth", type="eng_float", default=1000, + help="Filter bandwidth [default=%default]") + parser.add_option("-T", "--transition", type="eng_float", default=100, + help="Transition band [default=%default]") + parser.add_option("-A", "--attenuation", type="eng_float", default=80, + help="Stopband attenuation [default=%default]") + parser.add_option("-D", "--decimation", type="int", default=1, + help="Decmation factor [default=%default]") + (options, args) = parser.parse_args () + + put = example_fir_filter_ccc(options.nsamples, + options.samplerate, + options.bandwidth, + options.transition, + options.attenuation, + options.decimation) + put.run() + + data_src = scipy.array(put.vsnk_src.data()) + data_snk = scipy.array(put.vsnk_out.data()) + + # Plot the signals PSDs + nfft = 1024 + f1 = pylab.figure(1, figsize=(12,10)) + s1 = f1.add_subplot(1,1,1) + s1.psd(data_src, NFFT=nfft, noverlap=nfft/4, + Fs=options.samplerate) + s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4, + Fs=options.samplerate) + + f2 = pylab.figure(2, figsize=(12,10)) + s2 = f2.add_subplot(1,1,1) + s2.plot(data_src) + s2.plot(data_snk.real, 'g') + + pylab.show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/fir_filter_fff.py b/gr-filter/examples/fir_filter_fff.py new file mode 100755 index 0000000000..48769f00df --- /dev/null +++ b/gr-filter/examples/fir_filter_fff.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +from gnuradio import gr, filter +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +try: + import scipy +except ImportError: + print "Error: could not import scipy (http://www.scipy.org/)" + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + sys.exit(1) + +class example_fir_filter_fff(gr.top_block): + def __init__(self, N, fs, bw, tw, atten, D): + gr.top_block.__init__(self) + + self._nsamps = N + self._fs = fs + self._bw = bw + self._tw = tw + self._at = atten + self._decim = D + taps = filter.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at) + print "Num. Taps: ", len(taps) + + self.src = gr.noise_source_f(gr.GR_GAUSSIAN, 1) + self.head = gr.head(gr.sizeof_float, self._nsamps) + + self.filt0 = filter.fir_filter_fff(self._decim, taps) + + self.vsnk_src = gr.vector_sink_f() + self.vsnk_out = gr.vector_sink_f() + + self.connect(self.src, self.head, self.vsnk_src) + self.connect(self.head, self.filt0, self.vsnk_out) + +def main(): + parser = OptionParser(option_class=eng_option, conflict_handler="resolve") + parser.add_option("-N", "--nsamples", type="int", default=10000, + help="Number of samples to process [default=%default]") + parser.add_option("-s", "--samplerate", type="eng_float", default=8000, + help="System sample rate [default=%default]") + parser.add_option("-B", "--bandwidth", type="eng_float", default=1000, + help="Filter bandwidth [default=%default]") + parser.add_option("-T", "--transition", type="eng_float", default=100, + help="Transition band [default=%default]") + parser.add_option("-A", "--attenuation", type="eng_float", default=80, + help="Stopband attenuation [default=%default]") + parser.add_option("-D", "--decimation", type="int", default=1, + help="Decmation factor [default=%default]") + (options, args) = parser.parse_args () + + put = example_fir_filter_fff(options.nsamples, + options.samplerate, + options.bandwidth, + options.transition, + options.attenuation, + options.decimation) + put.run() + + data_src = scipy.array(put.vsnk_src.data()) + data_snk = scipy.array(put.vsnk_out.data()) + + # Plot the signals PSDs + nfft = 1024 + f1 = pylab.figure(1, figsize=(12,10)) + s1 = f1.add_subplot(1,1,1) + s1.psd(data_src, NFFT=nfft, noverlap=nfft/4, + Fs=options.samplerate) + s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4, + Fs=options.samplerate) + + f2 = pylab.figure(2, figsize=(12,10)) + s2 = f2.add_subplot(1,1,1) + s2.plot(data_src) + s2.plot(data_snk.real, 'g') + + pylab.show() + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/fmtest.py b/gr-filter/examples/fmtest.py new file mode 100755 index 0000000000..9b02526d9b --- /dev/null +++ b/gr-filter/examples/fmtest.py @@ -0,0 +1,226 @@ +#!/usr/bin/env python +# +# Copyright 2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, blks2 +from gnuradio import filter +import sys, math, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + + +class fmtx(gr.hier_block2): + def __init__(self, lo_freq, audio_rate, if_rate): + + gr.hier_block2.__init__(self, "build_fm", + gr.io_signature(1, 1, gr.sizeof_float), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + + fmtx = blks2.nbfm_tx (audio_rate, if_rate, max_dev=5e3, tau=75e-6) + + # Local oscillator + lo = gr.sig_source_c (if_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + lo_freq, #frequency + 1.0, # amplitude + 0) # DC Offset + mixer = gr.multiply_cc () + + self.connect (self, fmtx, (mixer, 0)) + self.connect (lo, (mixer, 1)) + self.connect (mixer, self) + +class fmtest(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._nsamples = 1000000 + self._audio_rate = 8000 + + # Set up N channels with their own baseband and IF frequencies + self._N = 5 + chspacing = 16000 + freq = [10, 20, 30, 40, 50] + f_lo = [0, 1*chspacing, -1*chspacing, 2*chspacing, -2*chspacing] + + self._if_rate = 4*self._N*self._audio_rate + + # Create a signal source and frequency modulate it + self.sum = gr.add_cc () + for n in xrange(self._N): + sig = gr.sig_source_f(self._audio_rate, gr.GR_SIN_WAVE, freq[n], 0.5) + fm = fmtx(f_lo[n], self._audio_rate, self._if_rate) + self.connect(sig, fm) + self.connect(fm, (self.sum, n)) + + self.head = gr.head(gr.sizeof_gr_complex, self._nsamples) + self.snk_tx = gr.vector_sink_c() + self.channel = blks2.channel_model(0.1) + + self.connect(self.sum, self.head, self.channel, self.snk_tx) + + + # Design the channlizer + self._M = 10 + bw = chspacing/2.0 + t_bw = chspacing/10.0 + self._chan_rate = self._if_rate / self._M + self._taps = filter.firdes.low_pass_2(1, self._if_rate, bw, t_bw, + attenuation_dB=100, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + tpc = math.ceil(float(len(self._taps)) / float(self._M)) + + print "Number of taps: ", len(self._taps) + print "Number of channels: ", self._M + print "Taps per channel: ", tpc + + self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps) + + self.connect(self.channel, self.pfb) + + # Create a file sink for each of M output channels of the filter and connect it + self.fmdet = list() + self.squelch = list() + self.snks = list() + for i in xrange(self._M): + self.fmdet.append(blks2.nbfm_rx(self._audio_rate, self._chan_rate)) + self.squelch.append(blks2.standard_squelch(self._audio_rate*10)) + self.snks.append(gr.vector_sink_f()) + self.connect((self.pfb, i), self.fmdet[i], self.squelch[i], self.snks[i]) + + def num_tx_channels(self): + return self._N + + def num_rx_channels(self): + return self._M + +def main(): + + fm = fmtest() + + tstart = time.time() + fm.run() + tend = time.time() + + if 1: + fig1 = pylab.figure(1, figsize=(12,10), facecolor="w") + fig2 = pylab.figure(2, figsize=(12,10), facecolor="w") + fig3 = pylab.figure(3, figsize=(12,10), facecolor="w") + + Ns = 10000 + Ne = 100000 + + fftlen = 8192 + winfunc = scipy.blackman + + # Plot transmitted signal + fs = fm._if_rate + + d = fm.snk_tx.data()[Ns:Ns+Ne] + sp1_f = fig1.add_subplot(2, 1, 1) + + X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + visible=False) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + p1_f = sp1_f.plot(f_in, X_in, "b") + sp1_f.set_xlim([min(f_in), max(f_in)+1]) + sp1_f.set_ylim([-120.0, 20.0]) + + sp1_f.set_title("Input Signal", weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + sp1_t = fig1.add_subplot(2, 1, 2) + p1_t = sp1_t.plot(t_in, x_in.real, "b-o") + #p1_t = sp1_t.plot(t_in, x_in.imag, "r-o") + sp1_t.set_ylim([-5, 5]) + + # Set up the number of rows and columns for plotting the subfigures + Ncols = int(scipy.floor(scipy.sqrt(fm.num_rx_channels()))) + Nrows = int(scipy.floor(fm.num_rx_channels() / Ncols)) + if(fm.num_rx_channels() % Ncols != 0): + Nrows += 1 + + # Plot each of the channels outputs. Frequencies on Figure 2 and + # time signals on Figure 3 + fs_o = fm._audio_rate + for i in xrange(len(fm.snks)): + # remove issues with the transients at the beginning + # also remove some corruption at the end of the stream + # this is a bug, probably due to the corner cases + d = fm.snks[i].data()[Ns:Ne] + + sp2_f = fig2.add_subplot(Nrows, Ncols, 1+i) + X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + visible=False) + #X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + X_o = 10.0*scipy.log10(abs(X)) + #f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + f_o = scipy.arange(0, fs_o/2.0, fs_o/2.0/float(X_o.size)) + p2_f = sp2_f.plot(f_o, X_o, "b") + sp2_f.set_xlim([min(f_o), max(f_o)+0.1]) + sp2_f.set_ylim([-120.0, 20.0]) + sp2_f.grid(True) + + sp2_f.set_title(("Channel %d" % i), weight="bold") + sp2_f.set_xlabel("Frequency (kHz)") + sp2_f.set_ylabel("Power (dBW)") + + + Ts = 1.0/fs_o + Tmax = len(d)*Ts + t_o = scipy.arange(0, Tmax, Ts) + + x_t = scipy.array(d) + sp2_t = fig3.add_subplot(Nrows, Ncols, 1+i) + p2_t = sp2_t.plot(t_o, x_t.real, "b") + p2_t = sp2_t.plot(t_o, x_t.imag, "r") + sp2_t.set_xlim([min(t_o), max(t_o)+1]) + sp2_t.set_ylim([-1, 1]) + + sp2_t.set_xlabel("Time (s)") + sp2_t.set_ylabel("Amplitude") + + + pylab.show() + + +if __name__ == "__main__": + main() diff --git a/gr-filter/examples/interpolate.py b/gr-filter/examples/interpolate.py new file mode 100755 index 0000000000..56d78d597b --- /dev/null +++ b/gr-filter/examples/interpolate.py @@ -0,0 +1,240 @@ +#!/usr/bin/env python +# +# Copyright 2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio import filter +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 100000 # number of samples to use + self._fs = 2000 # initial sampling rate + self._interp = 5 # Interpolation rate for PFB interpolator + self._ainterp = 5.5 # Resampling rate for the PFB arbitrary resampler + + # Frequencies of the signals we construct + freq1 = 100 + freq2 = 200 + + # Create a set of taps for the PFB interpolator + # This is based on the post-interpolation sample rate + self._taps = filter.firdes.low_pass_2(self._interp, + self._interp*self._fs, + freq2+50, 50, + attenuation_dB=120, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + # Create a set of taps for the PFB arbitrary resampler + # The filter size is the number of filters in the filterbank; 32 will give very low side-lobes, + # and larger numbers will reduce these even farther + # The taps in this filter are based on a sampling rate of the filter size since it acts + # internally as an interpolator. + flt_size = 32 + self._taps2 = filter.firdes.low_pass_2(flt_size, + flt_size*self._fs, + freq2+50, 150, + attenuation_dB=120, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._interp)) + print "Number of taps: ", len(self._taps) + print "Number of filters: ", self._interp + print "Taps per channel: ", tpc + + # Create a couple of signals at different frequencies + self.signal1 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq1, 0.5) + self.signal2 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq2, 0.5) + self.signal = gr.add_cc() + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct the PFB interpolator filter + self.pfb = filter.pfb.interpolator_ccf(self._interp, self._taps) + + # Construct the PFB arbitrary resampler filter + self.pfb_ar = filter.pfb.arb_resampler_ccf(self._ainterp, self._taps2, flt_size) + self.snk_i = gr.vector_sink_c() + + #self.pfb_ar.pfb.print_taps() + #self.pfb.pfb.print_taps() + + # Connect the blocks + self.connect(self.signal1, self.head, (self.signal,0)) + self.connect(self.signal2, (self.signal,1)) + self.connect(self.signal, self.pfb) + self.connect(self.signal, self.pfb_ar) + self.connect(self.signal, self.snk_i) + + # Create the sink for the interpolated signals + self.snk1 = gr.vector_sink_c() + self.snk2 = gr.vector_sink_c() + self.connect(self.pfb, self.snk1) + self.connect(self.pfb_ar, self.snk2) + + +def main(): + tb = pfb_top_block() + + tstart = time.time() + tb.run() + tend = time.time() + print "Run time: %f" % (tend - tstart) + + + if 1: + fig1 = pylab.figure(1, figsize=(12,10), facecolor="w") + fig2 = pylab.figure(2, figsize=(12,10), facecolor="w") + fig3 = pylab.figure(3, figsize=(12,10), facecolor="w") + + Ns = 10000 + Ne = 10000 + + fftlen = 8192 + winfunc = scipy.blackman + + # Plot input signal + fs = tb._fs + + d = tb.snk_i.data()[Ns:Ns+Ne] + sp1_f = fig1.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + p1_f = sp1_f.plot(f_in, X_in, "b") + sp1_f.set_xlim([min(f_in), max(f_in)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + + sp1_f.set_title("Input Signal", weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + sp1_t = fig1.add_subplot(2, 1, 2) + p1_t = sp1_t.plot(t_in, x_in.real, "b-o") + #p1_t = sp1_t.plot(t_in, x_in.imag, "r-o") + sp1_t.set_ylim([-2.5, 2.5]) + + sp1_t.set_title("Input Signal", weight="bold") + sp1_t.set_xlabel("Time (s)") + sp1_t.set_ylabel("Amplitude") + + + # Plot output of PFB interpolator + fs_int = tb._fs*tb._interp + + sp2_f = fig2.add_subplot(2, 1, 1) + d = tb.snk1.data()[Ns:Ns+(tb._interp*Ne)] + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_o = scipy.arange(-fs_int/2.0, fs_int/2.0, fs_int/float(X_o.size)) + p2_f = sp2_f.plot(f_o, X_o, "b") + sp2_f.set_xlim([min(f_o), max(f_o)+1]) + sp2_f.set_ylim([-200.0, 50.0]) + + sp2_f.set_title("Output Signal from PFB Interpolator", weight="bold") + sp2_f.set_xlabel("Frequency (Hz)") + sp2_f.set_ylabel("Power (dBW)") + + Ts_int = 1.0/fs_int + Tmax = len(d)*Ts_int + + t_o = scipy.arange(0, Tmax, Ts_int) + x_o1 = scipy.array(d) + sp2_t = fig2.add_subplot(2, 1, 2) + p2_t = sp2_t.plot(t_o, x_o1.real, "b-o") + #p2_t = sp2_t.plot(t_o, x_o.imag, "r-o") + sp2_t.set_ylim([-2.5, 2.5]) + + sp2_t.set_title("Output Signal from PFB Interpolator", weight="bold") + sp2_t.set_xlabel("Time (s)") + sp2_t.set_ylabel("Amplitude") + + + # Plot output of PFB arbitrary resampler + fs_aint = tb._fs * tb._ainterp + + sp3_f = fig3.add_subplot(2, 1, 1) + d = tb.snk2.data()[Ns:Ns+(tb._interp*Ne)] + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_o = scipy.arange(-fs_aint/2.0, fs_aint/2.0, fs_aint/float(X_o.size)) + p3_f = sp3_f.plot(f_o, X_o, "b") + sp3_f.set_xlim([min(f_o), max(f_o)+1]) + sp3_f.set_ylim([-200.0, 50.0]) + + sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", weight="bold") + sp3_f.set_xlabel("Frequency (Hz)") + sp3_f.set_ylabel("Power (dBW)") + + Ts_aint = 1.0/fs_aint + Tmax = len(d)*Ts_aint + + t_o = scipy.arange(0, Tmax, Ts_aint) + x_o2 = scipy.array(d) + sp3_f = fig3.add_subplot(2, 1, 2) + p3_f = sp3_f.plot(t_o, x_o2.real, "b-o") + p3_f = sp3_f.plot(t_o, x_o1.real, "m-o") + #p3_f = sp3_f.plot(t_o, x_o2.imag, "r-o") + sp3_f.set_ylim([-2.5, 2.5]) + + sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", weight="bold") + sp3_f.set_xlabel("Time (s)") + sp3_f.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/reconstruction.py b/gr-filter/examples/reconstruction.py new file mode 100755 index 0000000000..9e38f3669c --- /dev/null +++ b/gr-filter/examples/reconstruction.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python +# +# Copyright 2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, digital +from gnuradio import filter + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +fftlen = 8192 + +def main(): + N = 10000 + fs = 2000.0 + Ts = 1.0/fs + t = scipy.arange(0, N*Ts, Ts) + + # When playing with the number of channels, be careful about the filter + # specs and the channel map of the synthesizer set below. + nchans = 10 + + # Build the filter(s) + bw = 1000 + tb = 400 + proto_taps = filter.firdes.low_pass_2(1, nchans*fs, + bw, tb, 80, + filter.firdes.WIN_BLACKMAN_hARRIS) + print "Filter length: ", len(proto_taps) + + + # Create a modulated signal + npwr = 0.01 + data = scipy.random.randint(0, 256, N) + rrc_taps = filter.firdes.root_raised_cosine(1, 2, 1, 0.35, 41) + + src = gr.vector_source_b(data.astype(scipy.uint8).tolist(), False) + mod = digital.bpsk_mod(samples_per_symbol=2) + chan = gr.channel_model(npwr) + rrc = filter.fft_filter_ccc(1, rrc_taps) + + # Split it up into pieces + channelizer = filter.pfb.channelizer_ccf(nchans, proto_taps, 2) + + # Put the pieces back together again + syn_taps = [nchans*t for t in proto_taps] + synthesizer = filter.pfb_synthesizer_ccf(nchans, syn_taps, True) + src_snk = gr.vector_sink_c() + snk = gr.vector_sink_c() + + # Remap the location of the channels + # Can be done in synth or channelizer (watch out for rotattions in + # the channelizer) + synthesizer.set_channel_map([ 0, 1, 2, 3, 4, + 15, 16, 17, 18, 19]) + + tb = gr.top_block() + tb.connect(src, mod, chan, rrc, channelizer) + tb.connect(rrc, src_snk) + + vsnk = [] + for i in xrange(nchans): + tb.connect((channelizer,i), (synthesizer, i)) + + vsnk.append(gr.vector_sink_c()) + tb.connect((channelizer,i), vsnk[i]) + + tb.connect(synthesizer, snk) + tb.run() + + sin = scipy.array(src_snk.data()[1000:]) + sout = scipy.array(snk.data()[1000:]) + + + # Plot original signal + fs_in = nchans*fs + f1 = pylab.figure(1, figsize=(16,12), facecolor='w') + s11 = f1.add_subplot(2,2,1) + s11.psd(sin, NFFT=fftlen, Fs=fs_in) + s11.set_title("PSD of Original Signal") + s11.set_ylim([-200, -20]) + + s12 = f1.add_subplot(2,2,2) + s12.plot(sin.real[1000:1500], "o-b") + s12.plot(sin.imag[1000:1500], "o-r") + s12.set_title("Original Signal in Time") + + start = 1 + skip = 4 + s13 = f1.add_subplot(2,2,3) + s13.plot(sin.real[start::skip], sin.imag[start::skip], "o") + s13.set_title("Constellation") + s13.set_xlim([-2, 2]) + s13.set_ylim([-2, 2]) + + # Plot channels + nrows = int(scipy.sqrt(nchans)) + ncols = int(scipy.ceil(float(nchans)/float(nrows))) + + f2 = pylab.figure(2, figsize=(16,12), facecolor='w') + for n in xrange(nchans): + s = f2.add_subplot(nrows, ncols, n+1) + s.psd(vsnk[n].data(), NFFT=fftlen, Fs=fs_in) + s.set_title("Channel {0}".format(n)) + s.set_ylim([-200, -20]) + + # Plot reconstructed signal + fs_out = 2*nchans*fs + f3 = pylab.figure(3, figsize=(16,12), facecolor='w') + s31 = f3.add_subplot(2,2,1) + s31.psd(sout, NFFT=fftlen, Fs=fs_out) + s31.set_title("PSD of Reconstructed Signal") + s31.set_ylim([-200, -20]) + + s32 = f3.add_subplot(2,2,2) + s32.plot(sout.real[1000:1500], "o-b") + s32.plot(sout.imag[1000:1500], "o-r") + s32.set_title("Reconstructed Signal in Time") + + start = 2 + skip = 4 + s33 = f3.add_subplot(2,2,3) + s33.plot(sout.real[start::skip], sout.imag[start::skip], "o") + s33.set_title("Constellation") + s33.set_xlim([-2, 2]) + s33.set_ylim([-2, 2]) + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gr-filter/examples/resampler.py b/gr-filter/examples/resampler.py new file mode 100755 index 0000000000..395e095cbd --- /dev/null +++ b/gr-filter/examples/resampler.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright 2009,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio import filter +import sys + +try: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class mytb(gr.top_block): + def __init__(self, fs_in, fs_out, fc, N=10000): + gr.top_block.__init__(self) + + rerate = float(fs_out) / float(fs_in) + print "Resampling from %f to %f by %f " %(fs_in, fs_out, rerate) + + # Creating our own taps + taps = gr.firdes.low_pass_2(32, 32, 0.25, 0.1, 80) + + self.src = gr.sig_source_c(fs_in, gr.GR_SIN_WAVE, fc, 1) + #self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1) + self.head = gr.head(gr.sizeof_gr_complex, N) + + # A resampler with our taps + self.resamp_0 = filter.pfb.arb_resampler_ccf(rerate, taps, + flt_size=32) + + # A resampler that just needs a resampling rate. + # Filter is created for us and designed to cover + # entire bandwidth of the input signal. + # An optional atten=XX rate can be used here to + # specify the out-of-band rejection (default=80). + self.resamp_1 = filter.pfb.arb_resampler_ccf(rerate) + + self.snk_in = gr.vector_sink_c() + self.snk_0 = gr.vector_sink_c() + self.snk_1 = gr.vector_sink_c() + + self.connect(self.src, self.head, self.snk_in) + self.connect(self.head, self.resamp_0, self.snk_0) + self.connect(self.head, self.resamp_1, self.snk_1) + +def main(): + fs_in = 8000 + fs_out = 20000 + fc = 1000 + N = 10000 + + tb = mytb(fs_in, fs_out, fc, N) + tb.run() + + + # Plot PSD of signals + nfftsize = 2048 + fig1 = pylab.figure(1, figsize=(10,10), facecolor="w") + sp1 = fig1.add_subplot(2,1,1) + sp1.psd(tb.snk_in.data(), NFFT=nfftsize, + noverlap=nfftsize/4, Fs = fs_in) + sp1.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0))) + sp1.set_xlim([-fs_in/2, fs_in/2]) + + sp2 = fig1.add_subplot(2,1,2) + sp2.psd(tb.snk_0.data(), NFFT=nfftsize, + noverlap=nfftsize/4, Fs = fs_out, + label="With our filter") + sp2.psd(tb.snk_1.data(), NFFT=nfftsize, + noverlap=nfftsize/4, Fs = fs_out, + label="With auto-generated filter") + sp2.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0))) + sp2.set_xlim([-fs_out/2, fs_out/2]) + sp2.legend() + + # Plot signals in time + Ts_in = 1.0/fs_in + Ts_out = 1.0/fs_out + t_in = scipy.arange(0, len(tb.snk_in.data())*Ts_in, Ts_in) + t_out = scipy.arange(0, len(tb.snk_0.data())*Ts_out, Ts_out) + + fig2 = pylab.figure(2, figsize=(10,10), facecolor="w") + sp21 = fig2.add_subplot(2,1,1) + sp21.plot(t_in, tb.snk_in.data()) + sp21.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0))) + sp21.set_xlim([t_in[100], t_in[200]]) + + sp22 = fig2.add_subplot(2,1,2) + sp22.plot(t_out, tb.snk_0.data(), + label="With our filter") + sp22.plot(t_out, tb.snk_1.data(), + label="With auto-generated filter") + sp22.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0))) + r = float(fs_out)/float(fs_in) + sp22.set_xlim([t_out[r * 100], t_out[r * 200]]) + sp22.legend() + + pylab.show() + +if __name__ == "__main__": + main() + diff --git a/gr-filter/examples/resampler_demo.grc b/gr-filter/examples/resampler_demo.grc new file mode 100644 index 0000000000..b3991ac198 --- /dev/null +++ b/gr-filter/examples/resampler_demo.grc @@ -0,0 +1,630 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Tue Jun 19 21:31:30 2012</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>resampler_demo</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value></value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>wx_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import math</value> + </param> + <param> + <key>_coordinate</key> + <value>(11, 59)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>rs_taps</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>firdes.low_pass(nphases, nphases, frac_bw, 0.5-frac_bw)</value> + </param> + <param> + <key>_coordinate</key> + <value>(273, 154)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_add_const_vxx</key> + <param> + <key>id</key> + <value>adder</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>const</key> + <value>-1.0</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(227, 303)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_throttle</key> + <param> + <key>id</key> + <value>throttle</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(227, 493)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_fftsink2</key> + <param> + <key>id</key> + <value>orig_fft</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>title</key> + <value>Original Spectrum</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>baseband_freq</key> + <value>0</value> + </param> + <param> + <key>y_per_div</key> + <value>10</value> + </param> + <param> + <key>y_divs</key> + <value>10</value> + </param> + <param> + <key>ref_level</key> + <value>30</value> + </param> + <param> + <key>ref_scale</key> + <value>2.0</value> + </param> + <param> + <key>fft_size</key> + <value>1024</value> + </param> + <param> + <key>fft_rate</key> + <value>30</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0</value> + </param> + <param> + <key>win</key> + <value>None</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value>1, 0, 1, 3</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(409, 289)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>gr_sig_source_x</key> + <param> + <key>id</key> + <value>tri_source</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>waveform</key> + <value>gr.GR_TRI_WAVE</value> + </param> + <param> + <key>freq</key> + <value>0.05</value> + </param> + <param> + <key>amp</key> + <value>2.0</value> + </param> + <param> + <key>offset</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(21, 271)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>nphases</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>32</value> + </param> + <param> + <key>_coordinate</key> + <value>(185, 153)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_static_text</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Sample Rate</value> + </param> + <param> + <key>value</key> + <value>44100</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>grid_pos</key> + <value>0, 0, 1, 1</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(179, 14)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_static_text</key> + <param> + <key>id</key> + <value>new_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Resampled Rate</value> + </param> + <param> + <key>value</key> + <value>48000</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>grid_pos</key> + <value>0, 1, 1, 1</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(328, 15)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_static_text</key> + <param> + <key>id</key> + <value>frac_bw</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Fractional Bandwidth</value> + </param> + <param> + <key>value</key> + <value>0.45</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>formatter</key> + <value>lambda x: "%0.2f"%x</value> + </param> + <param> + <key>grid_pos</key> + <value>0,2,1,1</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(473, 14)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_frequency_modulator_fc</key> + <param> + <key>id</key> + <value>fm_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>sensitivity</key> + <value>math.pi</value> + </param> + <param> + <key>_coordinate</key> + <value>(411, 493)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_fftsink2</key> + <param> + <key>id</key> + <value>resamp_fft</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>title</key> + <value>Resampled Spectrum</value> + </param> + <param> + <key>samp_rate</key> + <value>new_rate</value> + </param> + <param> + <key>baseband_freq</key> + <value>0</value> + </param> + <param> + <key>y_per_div</key> + <value>10</value> + </param> + <param> + <key>y_divs</key> + <value>10</value> + </param> + <param> + <key>ref_level</key> + <value>30</value> + </param> + <param> + <key>ref_scale</key> + <value>2.0</value> + </param> + <param> + <key>fft_size</key> + <value>1024</value> + </param> + <param> + <key>fft_rate</key> + <value>30</value> + </param> + <param> + <key>peak_hold</key> + <value>True</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0</value> + </param> + <param> + <key>win</key> + <value>None</value> + </param> + <param> + <key>win_size</key> + <value></value> + </param> + <param> + <key>grid_pos</key> + <value>2, 0, 1, 3</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(640, 256)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>pfb_arb_resampler_xxx</key> + <param> + <key>id</key> + <value>pfb_arb_resampler_xxx_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>ccf</value> + </param> + <param> + <key>rrate</key> + <value>float(new_rate)/samp_rate</value> + </param> + <param> + <key>taps</key> + <value>rs_taps</value> + </param> + <param> + <key>nfilts</key> + <value>nphases</value> + </param> + <param> + <key>_coordinate</key> + <value>(649, 469)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>tri_source</source_block_id> + <sink_block_id>adder</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>adder</source_block_id> + <sink_block_id>throttle</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fm_mod</source_block_id> + <sink_block_id>orig_fft</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>throttle</source_block_id> + <sink_block_id>fm_mod</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fm_mod</source_block_id> + <sink_block_id>pfb_arb_resampler_xxx_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>pfb_arb_resampler_xxx_0</source_block_id> + <sink_block_id>resamp_fft</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gr-filter/examples/synth_filter.py b/gr-filter/examples/synth_filter.py new file mode 100755 index 0000000000..a5b6fdf4cb --- /dev/null +++ b/gr-filter/examples/synth_filter.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# +# Copyright 2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +from gnuradio import filter +import sys + +try: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +def main(): + N = 1000000 + fs = 8000 + + freqs = [100, 200, 300, 400, 500] + nchans = 7 + + sigs = list() + for fi in freqs: + s = gr.sig_source_c(fs, gr.GR_SIN_WAVE, fi, 1) + sigs.append(s) + + taps = filter.firdes.low_pass_2(len(freqs), fs, + fs/float(nchans)/2, 100, 100) + print "Num. Taps = %d (taps per filter = %d)" % (len(taps), + len(taps)/nchans) + filtbank = filter.pfb_synthesizer_ccf(nchans, taps) + + head = gr.head(gr.sizeof_gr_complex, N) + snk = gr.vector_sink_c() + + tb = gr.top_block() + tb.connect(filtbank, head, snk) + + for i,si in enumerate(sigs): + tb.connect(si, (filtbank, i)) + + tb.run() + + if 1: + f1 = pylab.figure(1) + s1 = f1.add_subplot(1,1,1) + s1.plot(snk.data()[1000:]) + + fftlen = 2048 + f2 = pylab.figure(2) + s2 = f2.add_subplot(1,1,1) + winfunc = scipy.blackman + s2.psd(snk.data()[10000:], NFFT=fftlen, + Fs = nchans*fs, + noverlap=fftlen/4, + window = lambda d: d*winfunc(fftlen)) + + pylab.show() + +if __name__ == "__main__": + main() diff --git a/gr-filter/examples/synth_to_chan.py b/gr-filter/examples/synth_to_chan.py new file mode 100755 index 0000000000..b5f4c958ef --- /dev/null +++ b/gr-filter/examples/synth_to_chan.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# +# Copyright 2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, blks2 +from gnuradio import filter +import sys + +try: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +def main(): + N = 1000000 + fs = 8000 + + freqs = [100, 200, 300, 400, 500] + nchans = 7 + + sigs = list() + fmtx = list() + for fi in freqs: + s = gr.sig_source_f(fs, gr.GR_SIN_WAVE, fi, 1) + fm = blks2.nbfm_tx (fs, 4*fs, max_dev=10000, tau=75e-6) + sigs.append(s) + fmtx.append(fm) + + syntaps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) + print "Synthesis Num. Taps = %d (taps per filter = %d)" % (len(syntaps), + len(syntaps)/nchans) + chtaps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) + print "Channelizer Num. Taps = %d (taps per filter = %d)" % (len(chtaps), + len(chtaps)/nchans) + filtbank = filter.pfb_synthesizer_ccf(nchans, syntaps) + channelizer = filter.pfb.channelizer_ccf(nchans, chtaps) + + noise_level = 0.01 + head = gr.head(gr.sizeof_gr_complex, N) + noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_level) + addnoise = gr.add_cc() + snk_synth = gr.vector_sink_c() + + tb = gr.top_block() + + tb.connect(noise, (addnoise,0)) + tb.connect(filtbank, head, (addnoise, 1)) + tb.connect(addnoise, channelizer) + tb.connect(addnoise, snk_synth) + + snk = list() + for i,si in enumerate(sigs): + tb.connect(si, fmtx[i], (filtbank, i)) + + for i in xrange(nchans): + snk.append(gr.vector_sink_c()) + tb.connect((channelizer, i), snk[i]) + + tb.run() + + if 1: + channel = 1 + data = snk[channel].data()[1000:] + + f1 = pylab.figure(1) + s1 = f1.add_subplot(1,1,1) + s1.plot(data[10000:10200] ) + s1.set_title(("Output Signal from Channel %d" % channel)) + + fftlen = 2048 + winfunc = scipy.blackman + #winfunc = scipy.hamming + + f2 = pylab.figure(2) + s2 = f2.add_subplot(1,1,1) + s2.psd(data, NFFT=fftlen, + Fs = nchans*fs, + noverlap=fftlen/4, + window = lambda d: d*winfunc(fftlen)) + s2.set_title(("Output PSD from Channel %d" % channel)) + + f3 = pylab.figure(3) + s3 = f3.add_subplot(1,1,1) + s3.psd(snk_synth.data()[1000:], NFFT=fftlen, + Fs = nchans*fs, + noverlap=fftlen/4, + window = lambda d: d*winfunc(fftlen)) + s3.set_title("Output of Synthesis Filter") + + pylab.show() + +if __name__ == "__main__": + main() diff --git a/gr-filter/gnuradio-filter.pc.in b/gr-filter/gnuradio-filter.pc.in new file mode 100644 index 0000000000..e4e83b350c --- /dev/null +++ b/gr-filter/gnuradio-filter.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnuradio-filter +Description: GNU Radio's filter signal processing blocks +Requires: gnuradio-core gnuradio-fft +Version: @LIBVER@ +Libs: -L${libdir} -lgnuradio-filter +Cflags: -I${includedir} diff --git a/gr-filter/grc/CMakeLists.txt b/gr-filter/grc/CMakeLists.txt new file mode 100644 index 0000000000..2e3fef4f07 --- /dev/null +++ b/gr-filter/grc/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +install(FILES + filter_block_tree.xml + dc_blocker_xx.xml + fft_filter_xxx.xml + fir_filter_xxx.xml + filter_delay_fc.xml + fractional_interpolator_xx.xml + freq_xlating_fir_filter_xxx.xml + hilbert_fc.xml + iir_filter_ffd.xml + interp_fir_filter_xxx.xml + pfb_arb_resampler.xml + pfb_channelizer.xml + pfb_decimator.xml + pfb_interpolator.xml + pfb_synthesizer.xml + rational_resampler_base_xxx.xml + single_pole_iir_filter_xx.xml + channel_model.xml + DESTINATION ${GRC_BLOCKS_DIR} + COMPONENT "filter_python" +) diff --git a/gr-filter/grc/channel_model.xml b/gr-filter/grc/channel_model.xml new file mode 100644 index 0000000000..6d780974a2 --- /dev/null +++ b/gr-filter/grc/channel_model.xml @@ -0,0 +1,61 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Channel Model +################################################### + --> +<block> + <name>Channel Model</name> + <key>channel_model</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.channel_model( + noise_voltage=$noise_voltage, + frequency_offset=$freq_offset, + epsilon=$epsilon, + taps=$taps, + noise_seed=$seed, +)</make> + <callback>set_noise_voltage($noise_voltage)</callback> + <callback>set_frequency_offset($freq_offset)</callback> + <callback>set_taps($taps)</callback> + <callback>set_timing_offset($epsilon)</callback> + <param> + <name>Noise Voltage</name> + <key>noise_voltage</key> + <value>0.0</value> + <type>real</type> + </param> + <param> + <name>Frequency Offset</name> + <key>freq_offset</key> + <value>0.0</value> + <type>real</type> + </param> + <param> + <name>Epsilon</name> + <key>epsilon</key> + <value>1.0</value> + <type>real</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <value>1.0 + 1.0j</value> + <type>complex_vector</type> + </param> + <param> + <name>Seed</name> + <key>seed</key> + <value>0</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/grc/dc_blocker_xx.xml b/gr-filter/grc/dc_blocker_xx.xml new file mode 100644 index 0000000000..9bce5e980b --- /dev/null +++ b/gr-filter/grc/dc_blocker_xx.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- +################################################### +## DC Blocker +################################################### + --> +<block> + <name>DC Blocker</name> + <key>dc_blocker_xx</key> + <import>from gnuradio import filter</import> + <make>filter.dc_blocker_$(type)($length, $long_form)</make> + <!-- <callback>set_length($length)</callback> --> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex</name> + <key>cc</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + </option> + <option> + <name>Float->Float</name> + <key>ff</key> + <opt>input:float</opt> + <opt>output:float</opt> + </option> + </param> + <param> + <name>Length</name> + <key>length</key> + <value>32</value> + <type>int</type> + </param> + <param> + <name>Long Form</name> + <key>long_form</key> + <value>True</value> + <type>bool</type> + </param> + + <sink> + <name>in</name> + <type>$type.input</type> + </sink> + <source> + <name>out</name> + <type>$type.output</type> + </source> +</block> diff --git a/gr-filter/grc/fft_filter_xxx.xml b/gr-filter/grc/fft_filter_xxx.xml new file mode 100644 index 0000000000..29612dffd6 --- /dev/null +++ b/gr-filter/grc/fft_filter_xxx.xml @@ -0,0 +1,59 @@ +<?xml version="1.0"?> +<!-- +################################################### +##FFT Filter +################################################### + --> +<block> + <name>FFT Filter</name> + <key>fft_filter_xxx</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.gr import firdes</import> + <make>filter.fft_filter_$(type)($decim, $taps, $nthreads)</make> + <callback>set_taps($taps)</callback> + <callback>set_nthreads($nthreads)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex (Complex Taps)</name> + <key>ccc</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Float->Float (Real Taps)</name> + <key>fff</key> + <opt>input:float</opt> + <opt>output:float</opt> + <opt>taps:real_vector</opt> + </option> + </param> + <param> + <name>Decimation</name> + <key>decim</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>$type.taps</type> + </param> + <param> + <name>Num. Threads</name> + <key>nthreads</key> + <value>1</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>$type.input</type> + </sink> + <source> + <name>out</name> + <type>$type.output</type> + </source> +</block> diff --git a/gr-filter/grc/filter_block_tree.xml b/gr-filter/grc/filter_block_tree.xml new file mode 100644 index 0000000000..711ce4059f --- /dev/null +++ b/gr-filter/grc/filter_block_tree.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> + +<!-- + Copyright 2012 Free Software Foundation, Inc. + + This file is part of GNU Radio + + GNU Radio is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GNU Radio is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNU Radio; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, + Boston, MA 02110-1301, USA. +--> + +<!-- +################################################### +##Block Tree for GR Filter blocks. +################################################### + --> +<cat> + <name></name> <!-- Blank for Root Name --> + <cat> + <name>Filters</name> + <block>dc_blocker_xx</block> + <block>fft_filter_xxx</block> + <block>fir_filter_xxx</block> + <block>filter_delay_fc</block> + <block>fractional_interpolator_xx</block> + <block>freq_xlating_fir_filter_xxx</block> + <block>hilbert_fc</block> + <block>iir_filter_ffd</block> + <block>interp_fir_filter_xxx</block> + <block>pfb_arb_resampler_xxx</block> + <block>pfb_channelizer_ccf</block> + <block>pfb_decimator_ccf</block> + <block>pfb_interpolator_ccf</block> + <block>pfb_synthesizer_ccf</block> + <block>rational_resampler_base_xxx</block> + <block>single_pole_iir_filter_xx</block> + <block>channel_model</block> + </cat> +</cat> diff --git a/gr-filter/grc/filter_delay_fc.xml b/gr-filter/grc/filter_delay_fc.xml new file mode 100644 index 0000000000..7b77c2caf9 --- /dev/null +++ b/gr-filter/grc/filter_delay_fc.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Filter Delay +################################################### + --> +<block> + <name>Filter Delay</name> + <key>filter_delay_fc</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.filter_delay_fc($taps)</make> + <param> + <name>Taps</name> + <key>taps</key> + <type>real_vector</type> + </param> + <sink> + <name>in</name> + <type>float</type> + </sink> + <sink> + <name>in</name> + <type>float</type> + <optional>1</optional> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/grc/fir_filter_xxx.xml b/gr-filter/grc/fir_filter_xxx.xml new file mode 100644 index 0000000000..3925eb5559 --- /dev/null +++ b/gr-filter/grc/fir_filter_xxx.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Decimating FIR Filter +################################################### + --> +<block> + <name>Decimating FIR Filter</name> + <key>fir_filter_xxx</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.fir_filter_$(type)($decim, $taps)</make> + <callback>set_taps($taps)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex (Complex Taps)</name> + <key>ccc</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Complex->Complex (Real Taps)</name> + <key>ccf</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Complex (Complex Taps)</name> + <key>fcc</key> + <opt>input:float</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Float->Float (Real Taps)</name> + <key>fff</key> + <opt>input:float</opt> + <opt>output:float</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Short (Real Taps)</name> + <key>fsf</key> + <opt>input:float</opt> + <opt>output:short</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Short->Complex (Complex Taps)</name> + <key>scc</key> + <opt>input:short</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + </param> + <param> + <name>Decimation</name> + <key>decim</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>$type.taps</type> + </param> + <sink> + <name>in</name> + <type>$type.input</type> + </sink> + <source> + <name>out</name> + <type>$type.output</type> + </source> +</block> diff --git a/gr-filter/grc/fractional_interpolator_xx.xml b/gr-filter/grc/fractional_interpolator_xx.xml new file mode 100644 index 0000000000..760e8bb060 --- /dev/null +++ b/gr-filter/grc/fractional_interpolator_xx.xml @@ -0,0 +1,46 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Fractional Interpolator +################################################### + --> +<block> + <name>Fractional Interpolator</name> + <key>fractional_interpolator_xx</key> + <import>from gnuradio import filter</import> + <make>filter.fractional_interpolator_$(type.fcn)($phase_shift, $interp_ratio)</make> + <callback>set_interp_ratio($interp_ratio)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>fcn:cc</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>fcn:ff</opt> + </option> + </param> + <param> + <name>Phase Shift</name> + <key>phase_shift</key> + <type>real</type> + </param> + <param> + <name>Interpolation Ratio</name> + <key>interp_ratio</key> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + </sink> + <source> + <name>out</name> + <type>$type</type> + </source> +</block> diff --git a/gr-filter/grc/freq_xlating_fir_filter_xxx.xml b/gr-filter/grc/freq_xlating_fir_filter_xxx.xml new file mode 100644 index 0000000000..178a42f487 --- /dev/null +++ b/gr-filter/grc/freq_xlating_fir_filter_xxx.xml @@ -0,0 +1,93 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Frequency Xlating Filter +################################################### + --> +<block> + <name>Frequency Xlating FIR Filter</name> + <key>freq_xlating_fir_filter_xxx</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.freq_xlating_fir_filter_$(type)($decim, $taps, $center_freq, $samp_rate)</make> + <callback>set_taps($taps)</callback> + <callback>set_center_freq($center_freq)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex (Complex Taps)</name> + <key>ccc</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Complex->Complex (Real Taps)</name> + <key>ccf</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Complex (Complex Taps)</name> + <key>fcc</key> + <opt>input:float</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Float->Complex (Real Taps)</name> + <key>fcf</key> + <opt>input:float</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Short->Complex (Complex Taps)</name> + <key>scc</key> + <opt>input:short</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Short->Complex (Real Taps)</name> + <key>scf</key> + <opt>input:short</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + </param> + <param> + <name>Decimation</name> + <key>decim</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>$type.taps</type> + </param> + <param> + <name>Center Frequency</name> + <key>center_freq</key> + <value>0</value> + <type>real</type> + </param> + <param> + <name>Sample Rate</name> + <key>samp_rate</key> + <value>samp_rate</value> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>$type.input</type> + </sink> + <source> + <name>out</name> + <type>$type.output</type> + </source> +</block> diff --git a/grc/blocks/gr_diff_decoder_bb.xml b/gr-filter/grc/hilbert_fc.xml index ea7cf17343..dd4c94b831 100644 --- a/grc/blocks/gr_diff_decoder_bb.xml +++ b/gr-filter/grc/hilbert_fc.xml @@ -1,25 +1,26 @@ <?xml version="1.0"?> <!-- ################################################### -##Differential Decoder +##Hilbert ################################################### --> <block> - <name>Differential Decoder</name> - <key>gr_diff_decoder_bb</key> - <import>from gnuradio import gr</import> - <make>gr.diff_decoder_bb($modulus)</make> + <name>Hilbert</name> + <key>hilbert_fc</key> + <import>from gnuradio import filter</import> + <make>filter.hilbert_fc($num_taps)</make> <param> - <name>Modulus</name> - <key>modulus</key> + <name>Num Taps</name> + <key>num_taps</key> + <value>64</value> <type>int</type> </param> <sink> <name>in</name> - <type>byte</type> + <type>float</type> </sink> <source> <name>out</name> - <type>byte</type> + <type>complex</type> </source> </block> diff --git a/gr-filter/grc/iir_filter_ffd.xml b/gr-filter/grc/iir_filter_ffd.xml new file mode 100644 index 0000000000..261aba320c --- /dev/null +++ b/gr-filter/grc/iir_filter_ffd.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!-- +################################################### +##IIR Filter +################################################### + --> +<block> + <name>IIR Filter</name> + <key>iir_filter_ffd</key> + <import>from gnuradio import filter</import> + <make>filter.iir_filter_ffd($fftaps, $fbtaps)</make> + <callback>set_taps($fftaps, $fbtaps)</callback> + <param> + <name>Feed-forward Taps</name> + <key>fftaps</key> + <type>real_vector</type> + </param> + <param> + <name>Feedback Taps</name> + <key>fbtaps</key> + <type>real_vector</type> + </param> + <sink> + <name>in</name> + <type>float</type> + </sink> + <source> + <name>out</name> + <type>float</type> + </source> +</block> diff --git a/gr-filter/grc/interp_fir_filter_xxx.xml b/gr-filter/grc/interp_fir_filter_xxx.xml new file mode 100644 index 0000000000..98a143f538 --- /dev/null +++ b/gr-filter/grc/interp_fir_filter_xxx.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Interpolating FIR Filter +################################################### + --> +<block> + <name>Interpolating FIR Filter</name> + <key>interp_fir_filter_xxx</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.interp_fir_filter_$(type)($interp, $taps)</make> + <callback>set_taps($taps)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex (Complex Taps)</name> + <key>ccc</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Complex->Complex (Real Taps)</name> + <key>ccf</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Complex (Complex Taps)</name> + <key>fcc</key> + <opt>input:float</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Float->Float (Real Taps)</name> + <key>fff</key> + <opt>input:float</opt> + <opt>output:float</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Short (Real Taps)</name> + <key>fsf</key> + <opt>input:float</opt> + <opt>output:short</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Short->Complex (Complex Taps)</name> + <key>scc</key> + <opt>input:short</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + </param> + <param> + <name>Interpolation</name> + <key>interp</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>$type.taps</type> + </param> + <sink> + <name>in</name> + <type>$type.input</type> + </sink> + <source> + <name>out</name> + <type>$type.output</type> + </source> +</block> diff --git a/gr-filter/grc/pfb_arb_resampler.xml b/gr-filter/grc/pfb_arb_resampler.xml new file mode 100644 index 0000000000..f3048000ac --- /dev/null +++ b/gr-filter/grc/pfb_arb_resampler.xml @@ -0,0 +1,61 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Polyphase Arbitrary Resampler +################################################### + --> +<block> + <name>Polyphase Arbitrary Resampler</name> + <key>pfb_arb_resampler_xxx</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.pfb_arb_resampler_$(type)( + $rrate, + $taps, + $nfilts) + </make> + <callback>set_taps($taps)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex (Real Taps)</name> + <key>ccf</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Float (Real Taps)</name> + <key>fff</key> + <opt>input:float</opt> + <opt>output:float</opt> + <opt>taps:real_vector</opt> + </option> + </param> + <param> + <name>Resampling Rate</name> + <key>rrate</key> + <type>real</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>$type.taps</type> + </param> + <param> + <name>Number of Filters</name> + <key>nfilts</key> + <value>32</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/grc/pfb_channelizer.xml b/gr-filter/grc/pfb_channelizer.xml new file mode 100644 index 0000000000..114abc0f06 --- /dev/null +++ b/gr-filter/grc/pfb_channelizer.xml @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Polyphase Channelizer +################################################### + --> +<block> + <name>Polyphase Channelizer</name> + <key>pfb_channelizer_ccf</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.pfb.channelizer_ccf( + $nchans, + $taps, + $osr, + $atten) +self.$(id).set_channel_map($ch_map) + </make> + <!-- Set taps not implemented yet + <callback>set_taps($taps)</callback> + --> + <callback>set_channel_map($ch_map)</callback> + + <param> + <name>Channels</name> + <key>nchans</key> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <value>None</value> + <type>real_vector</type> + </param> + <param> + <name>Over Sample Ratio</name> + <key>osr</key> + <value>1.0</value> + <type>real</type> + </param> + <param> + <name>Attenuation</name> + <key>atten</key> + <value>100</value> + <type>real</type> + </param> + <param> + <name>Channel Map</name> + <key>ch_map</key> + <value>[]</value> + <type>int_vector</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + <nports>$nchans</nports> + </source> +</block> diff --git a/gr-filter/grc/pfb_decimator.xml b/gr-filter/grc/pfb_decimator.xml new file mode 100644 index 0000000000..b0540d3e2c --- /dev/null +++ b/gr-filter/grc/pfb_decimator.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Polyphase Decimator +################################################### + --> +<block> + <name>Polyphase Decimator</name> + <key>pfb_decimator_ccf</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.pfb_decimator_ccf( + $decim, + $taps, + $channel) + </make> + <callback>set_taps($taps)</callback> + <param> + <name>Decimation</name> + <key>decim</key> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <value>None</value> + <type>real_vector</type> + </param> + <param> + <name>Output Channel</name> + <key>channel</key> + <value>0</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/grc/pfb_interpolator.xml b/gr-filter/grc/pfb_interpolator.xml new file mode 100644 index 0000000000..6004931235 --- /dev/null +++ b/gr-filter/grc/pfb_interpolator.xml @@ -0,0 +1,36 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Polyphase Interpolator +################################################### + --> +<block> + <name>Polyphase Interpolator</name> + <key>pfb_interpolator_ccf</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.pfb.interpolator_ccf( + $interp, + $taps) + </make> + <callback>set_taps($taps)</callback> + <param> + <name>Interpolation</name> + <key>interp</key> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <value>None</value> + <type>real_vector</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/grc/pfb_synthesizer.xml b/gr-filter/grc/pfb_synthesizer.xml new file mode 100644 index 0000000000..e84b25e62e --- /dev/null +++ b/gr-filter/grc/pfb_synthesizer.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Polyphase Synthesis Filterbank +################################################### + --> +<block> + <name>Polyphase Synthesizer</name> + <key>pfb_synthesizer_ccf</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.pfb_synthesizer_ccf( + $numchans, $taps, $twox) +self.$(id).set_channel_map($ch_map) + </make> + <callback>set_taps($taps)</callback> + <callback>set_channel_map($ch_map)</callback> + + <param> + <name>Channels</name> + <key>numchans</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>Connections</name> + <key>connections</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>real_vector</type> + </param> + <param> + <name>2x Sample Rate</name> + <key>twox</key> + <value>False</value> + <type>bool</type> + </param> + <param> + <name>Channel Map</name> + <key>ch_map</key> + <value>[]</value> + <type>int_vector</type> + </param> + <sink> + <name>in</name> + <type>complex</type> + <nports>$connections</nports> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-filter/grc/rational_resampler_base_xxx.xml b/gr-filter/grc/rational_resampler_base_xxx.xml new file mode 100644 index 0000000000..399bfc74c9 --- /dev/null +++ b/gr-filter/grc/rational_resampler_base_xxx.xml @@ -0,0 +1,86 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Rational Resampler Base +################################################### + --> +<block> + <name>Rational Resampler Base</name> + <key>rational_resampler_base_xxx</key> + <import>from gnuradio import filter</import> + <import>from gnuradio.filter import firdes</import> + <make>filter.rational_resampler_base_$(type)($interp, $decim, $taps)</make> + <callback>set_taps($taps)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex->Complex (Complex Taps)</name> + <key>ccc</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Complex->Complex (Real Taps)</name> + <key>ccf</key> + <opt>input:complex</opt> + <opt>output:complex</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Complex (Complex Taps)</name> + <key>fcc</key> + <opt>input:float</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + <option> + <name>Float->Float (Real Taps)</name> + <key>fff</key> + <opt>input:float</opt> + <opt>output:float</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Float->Short (Real Taps)</name> + <key>fsf</key> + <opt>input:float</opt> + <opt>output:short</opt> + <opt>taps:real_vector</opt> + </option> + <option> + <name>Short->Complex (Complex Taps)</name> + <key>scc</key> + <opt>input:short</opt> + <opt>output:complex</opt> + <opt>taps:complex_vector</opt> + </option> + </param> + <param> + <name>Interpolation</name> + <key>interp</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Decimation</name> + <key>decim</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>$type.taps</type> + </param> + <sink> + <name>in</name> + <type>$type.input</type> + </sink> + <source> + <name>out</name> + <type>$type.output</type> + </source> +</block> diff --git a/gr-filter/grc/single_pole_iir_filter_xx.xml b/gr-filter/grc/single_pole_iir_filter_xx.xml new file mode 100644 index 0000000000..3eaf52625f --- /dev/null +++ b/gr-filter/grc/single_pole_iir_filter_xx.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Single Pole IIR Filter +################################################### + --> +<block> + <name>Single Pole IIR Filter</name> + <key>single_pole_iir_filter_xx</key> + <import>from gnuradio import filter</import> + <make>filter.single_pole_iir_filter_$(type.fcn)($alpha, $vlen)</make> + <callback>set_taps($alpha)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>fcn:cc</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>fcn:ff</opt> + </option> + </param> + <param> + <name>Alpha</name> + <key>alpha</key> + <value>1.0</value> + <type>real</type> + </param> + <param> + <name>Vec Length</name> + <key>vlen</key> + <value>1</value> + <type>int</type> + </param> + <check>$vlen > 0</check> + <sink> + <name>in</name> + <type>$type</type> + <vlen>$vlen</vlen> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>$vlen</vlen> + </source> +</block> diff --git a/gr-filter/include/filter/CMakeLists.txt b/gr-filter/include/filter/CMakeLists.txt new file mode 100644 index 0000000000..c6bf109cde --- /dev/null +++ b/gr-filter/include/filter/CMakeLists.txt @@ -0,0 +1,116 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# generate helper scripts to expand templated files +######################################################################## +include(GrPython) + +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py " +#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_CORE_PYTHONPATH}') +os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' +os.chdir('${CMAKE_CURRENT_BINARY_DIR}') + +if __name__ == '__main__': + import build_utils + root, inp = sys.argv[1:3] + for sig in sys.argv[3:]: + name = re.sub ('X+', sig, root) + d = build_utils.standard_dict2(name, sig, 'filter') + build_utils.expand_template(d, inp) + +") + +macro(expand_h root) + #make a list of all the generated files + unset(expanded_files_h) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h) + endforeach(sig) + + #create a command to generate the files + add_custom_command( + OUTPUT ${expanded_files_h} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.h.t ${ARGN} + ) + + #install rules for the generated h files + list(APPEND generated_includes ${expanded_files_h}) +endmacro(expand_h) + +######################################################################## +# Invoke macro to generate various sources +####################################################################### +expand_h(fir_filter_XXX ccc ccf fcc fff fsf scc) +expand_h(freq_xlating_fir_filter_XXX ccc ccf fcc fcf scf scc) +expand_h(interp_fir_filter_XXX ccc ccf fcc fff fsf scc) +expand_h(rational_resampler_base_XXX ccc ccf fcc fff fsf scc) + +add_custom_target(filter_generated_includes DEPENDS + ${generated_includes} +) + +######################################################################## +# Install header files +######################################################################## +install(FILES + api.h + firdes.h + fir_filter.h + fir_filter_with_buffer.h + fft_filter.h + iir_filter.h + interpolator_taps.h + mmse_fir_interpolator_cc.h + mmse_fir_interpolator_ff.h + pm_remez.h + polyphase_filterbank.h + single_pole_iir.h + ${generated_includes} + adaptive_fir_ccc.h + adaptive_fir_ccf.h + dc_blocker_cc.h + dc_blocker_ff.h + filter_delay_fc.h + fft_filter_ccc.h + fft_filter_fff.h + fractional_interpolator_cc.h + fractional_interpolator_ff.h + hilbert_fc.h + iir_filter_ffd.h + pfb_arb_resampler_ccf.h + pfb_arb_resampler_fff.h + pfb_channelizer_ccf.h + pfb_decimator_ccf.h + pfb_interpolator_ccf.h + pfb_synthesizer_ccf.h + single_pole_iir_filter_cc.h + single_pole_iir_filter_ff.h + channel_model.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/filter + COMPONENT "filter_devel" +) + diff --git a/gr-filter/include/filter/adaptive_fir_ccc.h b/gr-filter/include/filter/adaptive_fir_ccc.h new file mode 100644 index 0000000000..261259957f --- /dev/null +++ b/gr-filter/include/filter/adaptive_fir_ccc.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H +#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H + +#include <filter/api.h> +#include <gr_sync_decimator.h> +#include <filter/fir_filter.h> + +namespace gr { + namespace filter { + + /*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter_blk + * + * This is a base class to implement an adaptive FIR + * filter. Generally, another block will inherit from this one to + * build a new type of adaptive filter such as an equalizer. + * + * This class implements two functions that are designed to be + * overloaded by the child class: error(gr_complex out) and + * update_tap(gr_complex tap, gr_complex in). + * + * The error() function calculates the error value that will be + * used to adjust the taps. The update_tap function then uses the + * error and the input signal value to update a particular + * tap. Typically, the error is calculated for a given output and + * then this is used in a loop to update all of the filter taps in + * a loop: + * + * \code + * d_error = error(sum); + * for(k = 0; k < l; k++) { + * update_tap(d_taps[ntaps-k-1], in[i+k]); + * } + * \endcode + * + * See digital::cma_equalizer_cc and digital::lms_dd_equalizer_cc + * for example usage. + */ + class FILTER_API adaptive_fir_ccc : virtual public gr_sync_decimator + { + public: + // gr::filter::adaptive_fir_ccc::sptr + typedef boost::shared_ptr<adaptive_fir_ccc> sptr; + + /*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and gr_complex taps + * + * \param name Provides a name to identify this type of algorithm + * \param decimation (interger) decimation rate of the filter + * \param taps (complex) filter taps + */ + static sptr make(const char *name, int decimation, + const std::vector<gr_complex> &taps); + + virtual void set_taps(const std::vector<gr_complex> &taps) = 0; + virtual std::vector<gr_complex> taps() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_H */ diff --git a/gr-filter/include/filter/adaptive_fir_ccf.h b/gr-filter/include/filter/adaptive_fir_ccf.h new file mode 100644 index 0000000000..0fd8d5746a --- /dev/null +++ b/gr-filter/include/filter/adaptive_fir_ccf.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H +#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H + +#include <filter/api.h> +#include <gr_sync_decimator.h> + +namespace gr { + namespace filter { + + /*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * \ingroup filter_blk + * + * This is a base class to implement an adaptive FIR + * filter. Generally, another block will inherit from this one to + * build a new type of adaptive filter such as an equalizer. + * + * This class implements two functions that are designed to be + * overloaded by the child class: error(gr_complex out) and + * update_tap(float tap, gr_complex in). + * + * The error() function calculates the error value that will be + * used to adjust the taps. The update_tap function then uses the + * error and the input signal value to update a particular + * tap. Typically, the error is calculated for a given output and + * then this is used in a loop to update all of the filter taps in + * a loop: + * + * \code + * d_error = error(sum); + * for(k = 0; k < l; k++) { + * update_tap(d_taps[ntaps-k-1], in[i+k]); + * } + * \endcode + */ + class FILTER_API adaptive_fir_ccf : virtual public gr_sync_decimator + { + public: + // gr::filter::adaptive_fir_ccf::sptr + typedef boost::shared_ptr<adaptive_fir_ccf> sptr; + + /*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * + * \param name Provides a name to identify this type of algorithm + * \param decimation (interger) decimation rate of the filter + * \param taps (real) filter taps + */ + static sptr make(const char *name, int decimation, + const std::vector<float> &taps); + + virtual void set_taps(const std::vector<float> &taps) = 0; + virtual std::vector<float> taps() = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_H */ diff --git a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i b/gr-filter/include/filter/api.h index 96dadaca5b..025b0bd4a7 100644 --- a/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i +++ b/gr-filter/include/filter/api.h @@ -1,6 +1,5 @@ -/* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,12 +19,15 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,diff_encoder_bb) +#ifndef INCLUDED_FILTER_API_H +#define INCLUDED_FILTER_API_H -gr_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); +#include <gruel/attributes.h> -class gr_diff_encoder_bb : public gr_sync_block -{ - private: - gr_diff_encoder_bb (unsigned int modulus); -}; +#ifdef gnuradio_filter_EXPORTS +# define FILTER_API __GR_ATTR_EXPORT +#else +# define FILTER_API __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_FILTER_API_H */ diff --git a/gr-filter/include/filter/channel_model.h b/gr-filter/include/filter/channel_model.h new file mode 100644 index 0000000000..2e808de8e5 --- /dev/null +++ b/gr-filter/include/filter/channel_model.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_CHANNEL_MODEL_H +#define INCLUDED_FILTER_CHANNEL_MODEL_H + +#include <filter/api.h> +#include <gr_hier_block2.h> +#include <gr_types.h> + +namespace gr { + namespace filter { + + /*! + * \brief channel simulator + * \ingroup misc_blk + * + * This block implements a basic channel model simulator that can + * be used to help evaluate, design, and test various signals, + * waveforms, and algorithms. This model allows the user to set + * the voltage of an AWGN noise source, a (normalized) frequency + * offset, a sample timing offset, and a noise seed to randomize + * the AWGN noise source. + * + * Multipath can be approximated in this model by using a FIR + * filter representation of a multipath delay profile.. + */ + class FILTER_API channel_model : virtual public gr_hier_block2 + { + public: + // gr::filter::channel_model::sptr + typedef boost::shared_ptr<channel_model> sptr; + + /*! \brief Build the channel simulator. + * + * \param noise_voltage The AWGN noise level as a voltage (to be + * calculated externally to meet, say, a + * desired SNR). + * \param frequency_offset The normalized frequency offset. 0 is + * no offset; 0.25 would be, for a digital + * modem, one quarter of the symbol rate. + * \param epsilon The sample timing offset to emulate the + * different rates between the sample clocks of + * the transmitter and receiver. 1.0 is no difference. + * \param taps Taps of a FIR filter to emulate a multipath delay profile. + * \param noise_seed A random number generator seed for the noise source. + */ + static sptr make(double noise_voltage=0.0, + double frequency_offset=0.0, + double epsilon=1.0, + const std::vector<gr_complex> &taps=std::vector<gr_complex>(1,1), + double noise_seed=3021); + + virtual void set_noise_voltage(double noise_voltage) = 0; + virtual void set_frequency_offset(double frequency_offset) = 0; + virtual void set_taps(const std::vector<gr_complex> &taps) = 0; + virtual void set_timing_offset(double epsilon) = 0; + + virtual double noise_voltage() const = 0; + virtual double frequency_offset() const = 0; + virtual std::vector<gr_complex> taps() const = 0; + virtual double timing_offset() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_CHANNEL_MODEL_H */ diff --git a/gr-filter/include/filter/dc_blocker_cc.h b/gr-filter/include/filter/dc_blocker_cc.h new file mode 100644 index 0000000000..df4c815d60 --- /dev/null +++ b/gr-filter/include/filter/dc_blocker_cc.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_DC_BLOCKER_CC_H +#define INCLUDED_FILTER_DC_BLOCKER_CC_H + +#include <filter/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace filter { + + class FILTER_API dc_blocker_cc : virtual public gr_sync_block + { + public: + + // gr::filter::dc_blocker_cc::sptr + typedef boost::shared_ptr<dc_blocker_cc> sptr; + + /*! + * \class dc_blocker_cc + * \brief a computationally efficient controllable DC blocker + * + * \ingroup filter_blk + * + * This block implements a computationally efficient DC blocker that produces + * a tighter notch filter around DC for a smaller group delay than an + * equivalent FIR filter or using a single pole IIR filter (though the IIR + * filter is computationally cheaper). + * + * The block defaults to using a delay line of length 32 and the long form + * of the filter. Optionally, the delay line length can be changed to alter + * the width of the DC notch (longer lines will decrease the width). + * + * The long form of the filter produces a nearly flat response outside of + * the notch but at the cost of a group delay of 2D-2. + * + * The short form of the filter does not have as flat a response in the + * passband but has a group delay of only D-1 and is cheaper to compute. + * + * The theory behind this block can be found in the paper: + * + * <B><EM>R. Yates, "DC Blocker Algorithms," IEEE Signal Processing Magazine, + * Mar. 2008, pp 132-134.</EM></B> + * + * \param D (int) the length of the delay line + * \param long_form (bool) whether to use long (true, default) or short form + */ + static sptr make(int D, bool long_form); + + virtual int group_delay() = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_DC_BLOCKER_CC_H */ diff --git a/gr-filter/include/filter/dc_blocker_ff.h b/gr-filter/include/filter/dc_blocker_ff.h new file mode 100644 index 0000000000..6ab4d5a3de --- /dev/null +++ b/gr-filter/include/filter/dc_blocker_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_DC_BLOCKER_FF_H +#define INCLUDED_FILTER_DC_BLOCKER_FF_H + +#include <filter/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace filter { + + class FILTER_API dc_blocker_ff : virtual public gr_sync_block + { + public: + + // gr::filter::dc_blocker_ff::sptr + typedef boost::shared_ptr<dc_blocker_ff> sptr; + + /*! + * \class dc_blocker_ff + * \brief a computationally efficient controllable DC blocker + * + * \ingroup filter_blk + * + * This block implements a computationally efficient DC blocker that produces + * a tighter notch filter around DC for a smaller group delay than an + * equivalent FIR filter or using a single pole IIR filter (though the IIR + * filter is computationally cheaper). + * + * The block defaults to using a delay line of length 32 and the long form + * of the filter. Optionally, the delay line length can be changed to alter + * the width of the DC notch (longer lines will decrease the width). + * + * The long form of the filter produces a nearly flat response outside of + * the notch but at the cost of a group delay of 2D-2. + * + * The short form of the filter does not have as flat a response in the + * passband but has a group delay of only D-1 and is cheaper to compute. + * + * The theory behind this block can be found in the paper: + * + * <B><EM>R. Yates, "DC Blocker Algorithms," IEEE Signal Processing Magazine, + * Mar. 2008, pp 132-134.</EM></B> + * + * \param D (int) the length of the delay line + * \param long_form (bool) whether to use long (true, default) or short form + */ + static sptr make(int D, bool long_form=true); + + virtual int group_delay() = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_DC_BLOCKER_FF_H */ diff --git a/gr-filter/include/filter/fft_filter.h b/gr-filter/include/filter/fft_filter.h new file mode 100644 index 0000000000..8c7d6cf786 --- /dev/null +++ b/gr-filter/include/filter/fft_filter.h @@ -0,0 +1,171 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FFT_FILTER_H +#define INCLUDED_FILTER_FFT_FILTER_H + +#include <filter/api.h> +#include <vector> +#include <gr_complex.h> +#include <fft/fft.h> + +namespace gr { + namespace filter { + namespace kernel { + /*! + * \brief Fast FFT filter with float input, float output and float taps + * \ingroup filter_blk + */ + class FILTER_API fft_filter_fff + { + private: + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + int d_decimation; + fft::fft_real_fwd *d_fwdfft; // forward "plan" + fft::fft_real_rev *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use + std::vector<float> d_tail; // state carried between blocks for overlap-add + std::vector<float> d_new_taps; + gr_complex *d_xformed_taps; // Fourier xformed taps + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + + public: + /*! + * \brief Construct an FFT filter for float vectors with the given taps and decimation rate. + * + * This is the basic implementation for performing FFT filter for fast convolution + * in other blocks for complex vectors (such as fft_filter_ccc). + * + * \param decimation The decimation rate of the filter (int) + * \param taps The filter taps (complex) + * \param nthreads The number of threads for the FFT to use (int) + */ + fft_filter_fff(int decimation, + const std::vector<float> &taps, + int nthreads=1); + + ~fft_filter_fff(); + + /*! + * \brief Set new taps for the filter. + * + * Sets new taps and resets the class properties to handle different sizes + * \param taps The filter taps (complex) + */ + int set_taps(const std::vector<float> &taps); + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + /*! + * \brief Perform the filter operation + * + * \param nitems The number of items to produce + * \param input The input vector to be filtered + * \param output The result of the filter operation + */ + int filter(int nitems, const float *input, float *output); + }; + + + /*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter_blk + */ + class FILTER_API fft_filter_ccc + { + private: + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + int d_decimation; + fft::fft_complex *d_fwdfft; // forward "plan" + fft::fft_complex *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use + std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add + std::vector<gr_complex> d_new_taps; + gr_complex *d_xformed_taps; // Fourier xformed taps + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + + public: + /*! + * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate. + * + * This is the basic implementation for performing FFT filter for fast convolution + * in other blocks for complex vectors (such as fft_filter_ccc). + * + * \param decimation The decimation rate of the filter (int) + * \param taps The filter taps (complex) + * \param nthreads The number of threads for the FFT to use (int) + */ + fft_filter_ccc(int decimation, + const std::vector<gr_complex> &taps, + int nthreads=1); + + ~fft_filter_ccc(); + + /*! + * \brief Set new taps for the filter. + * + * Sets new taps and resets the class properties to handle different sizes + * \param taps The filter taps (complex) + */ + int set_taps(const std::vector<gr_complex> &taps); + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + /*! + * \brief Perform the filter operation + * + * \param nitems The number of items to produce + * \param input The input vector to be filtered + * \param output The result of the filter operation + */ + int filter(int nitems, const gr_complex *input, gr_complex *output); + }; + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FFT_FILTER_H */ diff --git a/gr-filter/include/filter/fft_filter_ccc.h b/gr-filter/include/filter/fft_filter_ccc.h new file mode 100644 index 0000000000..acec932775 --- /dev/null +++ b/gr-filter/include/filter/fft_filter_ccc.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FFT_FILTER_CCC_H +#define INCLUDED_FILTER_FFT_FILTER_CCC_H + +#include <filter/api.h> +#include <gr_sync_decimator.h> + +namespace gr { + namespace filter { + + class FILTER_API fft_filter_ccc : virtual public gr_sync_decimator + { + public: + // gr::filter::fft_filter_ccc::sptr + typedef boost::shared_ptr<fft_filter_ccc> sptr; + + /*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter_blk + * + * This block implements a complex decimating filter using the + * fast convolution method via an FFT. The decimation factor is + * an interger that is greater than or equal to 1. + * + * The filter takes a set of complex (or real) taps to use in + * the filtering operation. These taps can be defined as + * anything that satisfies the user's filtering needs. For + * standard filters such as lowpass, highpass, bandpass, etc., + * the filter.firdes and filter.optfir classes provide + * convenient generating methods. + * + * This filter is implemented by using the FFTW package to + * perform the required FFTs. An optional argument, nthreads, + * may be passed to the constructor (or set using the + * set_nthreads member function) to split the FFT among N number + * of threads. This can improve performance on very large FFTs + * (that is, if the number of taps used is very large) if you + * have enough threads/cores to support it. + * + * \param decimation >= 1 + * \param taps complex filter taps + * \param nthreads number of threads for the FFT to use + */ + static sptr make(int decimation, + const std::vector<gr_complex> &taps, + int nthreads=1); + + virtual void set_taps(const std::vector<gr_complex> &taps) = 0; + virtual std::vector<gr_complex> taps() const = 0; + + /*! + * \brief Set number of threads to use. + */ + virtual void set_nthreads(int n) = 0; + + /*! + * \brief Get number of threads being used. + */ + virtual int nthreads() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FFT_FILTER_CCC_H */ diff --git a/gr-filter/include/filter/fft_filter_fff.h b/gr-filter/include/filter/fft_filter_fff.h new file mode 100644 index 0000000000..d8140325f2 --- /dev/null +++ b/gr-filter/include/filter/fft_filter_fff.h @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FFT_FILTER_FFF_H +#define INCLUDED_FILTER_FFT_FILTER_FFF_H + +#include <filter/api.h> +#include <gr_sync_decimator.h> + +namespace gr { + namespace filter { + + class FILTER_API fft_filter_fff : virtual public gr_sync_decimator + { + public: + // gr::filter::fft_filter_fff::sptr + typedef boost::shared_ptr<fft_filter_fff> sptr; + + /*! + * \brief Fast FFT filter with float input, float output and float taps + * \ingroup filter_blk + * + * This block implements a real-value decimating filter using + * the fast convolution method via an FFT. The decimation factor + * is an interger that is greater than or equal to 1. + * + * The filter takes a set of real-valued taps to use in + * the filtering operation. These taps can be defined as + * anything that satisfies the user's filtering needs. For + * standard filters such as lowpass, highpass, bandpass, etc., + * the filter.firdes and filter.optfir classes provide + * convenient generating methods. + * + * This filter is implemented by using the FFTW package to + * perform the required FFTs. An optional argument, nthreads, + * may be passed to the constructor (or set using the + * set_nthreads member function) to split the FFT among N number + * of threads. This can improve performance on very large FFTs + * (that is, if the number of taps used is very large) if you + * have enough threads/cores to support it. + * + * \param decimation >= 1 + * \param taps float filter taps + * \param nthreads number of threads for the FFT to use + */ + static sptr make(int decimation, + const std::vector<float> &taps, + int nthreads=1); + + virtual void set_taps(const std::vector<float> &taps) = 0; + virtual std::vector<float> taps() const = 0; + + /*! + * \brief Set number of threads to use. + */ + virtual void set_nthreads(int n) = 0; + + /*! + * \brief Get number of threads being used. + */ + virtual int nthreads() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FFT_FILTER_FFF_H */ diff --git a/gr-filter/include/filter/filter_delay_fc.h b/gr-filter/include/filter/filter_delay_fc.h new file mode 100644 index 0000000000..8a84a6a0e5 --- /dev/null +++ b/gr-filter/include/filter/filter_delay_fc.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FILTER_DELAY_FC_H +#define INCLUDED_FILTER_FILTER_DELAY_FC_H + +#include <filter/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace filter { + + class FILTER_API filter_delay_fc : virtual public gr_sync_block + { + public: + + // gr::filter::filter_delay_fc::sptr + typedef boost::shared_ptr<filter_delay_fc> sptr; + + /*! + * \brief Filter-Delay Combination Block. + * \ingroup filter_blk + * + * The block takes one or two float stream and outputs a complex + * stream. + * + * If only one float stream is input, the real output is a + * delayed version of this input and the imaginary output is the + * filtered output. + * + * If two floats are connected to the input, then the real + * output is the delayed version of the first input, and the + * imaginary output is the filtered output. + * + * The delay in the real path accounts for the group delay + * introduced by the filter in the imaginary path. The filter + * taps needs to be calculated before initializing this block. + * + */ + static sptr make(const std::vector<float> &taps); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FILTER_DELAY_FC_H */ diff --git a/gr-filter/include/filter/fir_filter.h b/gr-filter/include/filter/fir_filter.h new file mode 100644 index 0000000000..e861112681 --- /dev/null +++ b/gr-filter/include/filter/fir_filter.h @@ -0,0 +1,222 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FIR_FILTER_H +#define INCLUDED_FILTER_FIR_FILTER_H + +#include <filter/api.h> +#include <vector> +#include <gr_complex.h> + +namespace gr { + namespace filter { + namespace kernel { + + class FILTER_API fir_filter_fff + { + public: + fir_filter_fff(int decimation, + const std::vector<float> &taps); + ~fir_filter_fff(); + + void set_taps(const std::vector<float> &taps); + std::vector<float> taps() const; + unsigned int ntaps() const; + + float filter(const float input[]); + void filterN(float output[], + const float input[], + unsigned long n); + void filterNdec(float output[], + const float input[], + unsigned long n, + unsigned int decimate); + + protected: + std::vector<float> d_taps; + unsigned int d_ntaps; + float **d_aligned_taps; + float *d_output; + int d_align; + int d_naligned; + }; + + /**************************************************************/ + + class FILTER_API fir_filter_ccf + { + public: + fir_filter_ccf(int decimation, + const std::vector<float> &taps); + ~fir_filter_ccf(); + + void set_taps(const std::vector<float> &taps); + std::vector<float> taps() const; + unsigned int ntaps() const; + + gr_complex filter(const gr_complex input[]); + void filterN(gr_complex output[], + const gr_complex input[], + unsigned long n); + void filterNdec(gr_complex output[], + const gr_complex input[], + unsigned long n, + unsigned int decimate); + + protected: + std::vector<float> d_taps; + unsigned int d_ntaps; + float **d_aligned_taps; + gr_complex *d_output; + int d_align; + int d_naligned; + }; + + /**************************************************************/ + + class FILTER_API fir_filter_fcc + { + public: + fir_filter_fcc(int decimation, + const std::vector<gr_complex> &taps); + ~fir_filter_fcc(); + + void set_taps(const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps() const; + unsigned int ntaps() const; + + gr_complex filter(const float input[]); + void filterN(gr_complex output[], + const float input[], + unsigned long n); + void filterNdec(gr_complex output[], + const float input[], + unsigned long n, + unsigned int decimate); + + protected: + std::vector<gr_complex> d_taps; + unsigned int d_ntaps; + gr_complex **d_aligned_taps; + gr_complex *d_output; + int d_align; + int d_naligned; + }; + + /**************************************************************/ + + class FILTER_API fir_filter_ccc + { + public: + fir_filter_ccc(int decimation, + const std::vector<gr_complex> &taps); + ~fir_filter_ccc(); + + void set_taps(const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps() const; + unsigned int ntaps() const; + + gr_complex filter(const gr_complex input[]); + void filterN(gr_complex output[], + const gr_complex input[], + unsigned long n); + void filterNdec(gr_complex output[], + const gr_complex input[], + unsigned long n, + unsigned int decimate); + + protected: + std::vector<gr_complex> d_taps; + unsigned int d_ntaps; + gr_complex **d_aligned_taps; + gr_complex *d_output; + int d_align; + int d_naligned; + }; + + /**************************************************************/ + + class FILTER_API fir_filter_scc + { + public: + fir_filter_scc(int decimation, + const std::vector<gr_complex> &taps); + ~fir_filter_scc(); + + void set_taps(const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps() const; + unsigned int ntaps() const; + + gr_complex filter(const short input[]); + void filterN(gr_complex output[], + const short input[], + unsigned long n); + void filterNdec(gr_complex output[], + const short input[], + unsigned long n, + unsigned int decimate); + + protected: + std::vector<gr_complex> d_taps; + unsigned int d_ntaps; + gr_complex **d_aligned_taps; + gr_complex *d_output; + int d_align; + int d_naligned; + }; + + /**************************************************************/ + + class FILTER_API fir_filter_fsf + { + public: + fir_filter_fsf(int decimation, + const std::vector<float> &taps); + ~fir_filter_fsf(); + + void set_taps(const std::vector<float> &taps); + std::vector<float> taps() const; + unsigned int ntaps() const; + + short filter(const float input[]); + void filterN(short output[], + const float input[], + unsigned long n); + void filterNdec(short output[], + const float input[], + unsigned long n, + unsigned int decimate); + + protected: + std::vector<float> d_taps; + unsigned int d_ntaps; + float **d_aligned_taps; + short *d_output; + int d_align; + int d_naligned; + }; + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FIR_FILTER_H */ diff --git a/gr-filter/include/filter/fir_filter_XXX.h.t b/gr-filter/include/filter/fir_filter_XXX.h.t new file mode 100644 index 0000000000..98e82f510d --- /dev/null +++ b/gr-filter/include/filter/fir_filter_XXX.h.t @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/api.h> +#include <gr_sync_decimator.h> + +namespace gr { + namespace filter { + + /*! + * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps + * \ingroup filter_blk + * + * The fir_filter_XXX blocks create finite impulse response + * (FIR) filters that perform the convolution in the time + * domain: + * + * \code + * out = 0 + * for i in ntaps: + * out += input[n-i] * taps[i] + * \endcode + * + * The taps are a C++ vector (or Python list) of values of the + * type specified by the third letter in the block's suffix. For + * this block, the value is of type @TAP_TYPE@. Taps can be + * created using the firdes or optfir tools. + * + * These versions of the filter can also act as down-samplers + * (or decimators) by specifying an integer value for \p + * decimation. + * + */ + class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator + { + public: + + // gr::filter::@BASE_NAME@::sptr + typedef boost::shared_ptr<@BASE_NAME@> sptr; + + /*! + * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps + * \ingroup filter_blk + * + * \param decimation set the integer decimation rate + * \param taps a vector/list of taps of type @TAP_TYPE@ + */ + static sptr make(int decimation, + const std::vector<@TAP_TYPE@> &taps); + + virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0; + virtual std::vector<@TAP_TYPE@> taps() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/include/filter/fir_filter_with_buffer.h b/gr-filter/include/filter/fir_filter_with_buffer.h new file mode 100644 index 0000000000..007eae3fa6 --- /dev/null +++ b/gr-filter/include/filter/fir_filter_with_buffer.h @@ -0,0 +1,326 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FIR_FILTER_WITH_BUFFER_H +#define INCLUDED_FILTER_FIR_FILTER_WITH_BUFFER_H + +#include <filter/api.h> +#include <vector> +#include <gr_complex.h> + +namespace gr { + namespace filter { + namespace kernel { + + /*! + * \brief FIR with internal buffer for float input, float output and float taps. + * \ingroup filter + */ + class FILTER_API fir_filter_with_buffer_fff + { + private: + std::vector<float> d_taps; + unsigned int d_ntaps; + float *d_buffer_ptr; + float *d_buffer; + unsigned int d_idx; + float **d_aligned_taps; + float *d_output; + int d_align; + int d_naligned; + + public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + fir_filter_with_buffer_fff(const std::vector<float> &taps); + + ~fir_filter_with_buffer_fff(); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input is a single input value of the filter type + * + * \returns the filtered input value. + */ + float filter(float input); + + /*! + * \brief compute a single output value; designed for decimating filters. + * + * \p input is a single input value of the filter type. The value of dec is the + * decimating value of the filter, so input[] must have dec valid values. + * The filter pushes dec number of items onto the circ. buffer before computing + * a single output. + * + * \returns the filtered input value. + */ + float filter(const float input[], unsigned long dec); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN(float output[], + const float input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec(float output[], const float input[], + unsigned long n, unsigned long decimate); + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned int ntaps() const { return d_ntaps; } + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps(const std::vector<float> &taps); + + /*! + * \return current taps + */ + std::vector<float> taps() const; + }; + + + /**************************************************************/ + + + /*! + * \brief FIR with internal buffer for gr_complex input, gr_complex output and gr_complex taps. + * \ingroup filter + */ + class FILTER_API fir_filter_with_buffer_ccc + { + private: + std::vector<gr_complex> d_taps; + unsigned int d_ntaps; + gr_complex *d_buffer_ptr; + gr_complex *d_buffer; + unsigned int d_idx; + gr_complex **d_aligned_taps; + gr_complex *d_output; + int d_align; + int d_naligned; + + public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + fir_filter_with_buffer_ccc(const std::vector<gr_complex> &taps); + + ~fir_filter_with_buffer_ccc(); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input is a single input value of the filter type + * + * \returns the filtered input value. + */ + gr_complex filter(gr_complex input); + + /*! + * \brief compute a single output value; designed for decimating filters. + * + * \p input is a single input value of the filter type. The value of dec is the + * decimating value of the filter, so input[] must have dec valid values. + * The filter pushes dec number of items onto the circ. buffer before computing + * a single output. + * + * \returns the filtered input value. + */ + gr_complex filter(const gr_complex input[], unsigned long dec); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN(gr_complex output[], + const gr_complex input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec(gr_complex output[], const gr_complex input[], + unsigned long n, unsigned long decimate); + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned int ntaps() const { return d_ntaps; } + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps(const std::vector<gr_complex> &taps); + + /*! + * \return current taps + */ + std::vector<gr_complex> taps() const; + }; + + + /**************************************************************/ + + + /*! + * \brief FIR with internal buffer for gr_complex input, gr_complex output and gr_complex taps. + * \ingroup filter + */ + class FILTER_API fir_filter_with_buffer_ccf + { + private: + std::vector<float> d_taps; + unsigned int d_ntaps; + gr_complex *d_buffer_ptr; + gr_complex *d_buffer; + unsigned int d_idx; + float **d_aligned_taps; + gr_complex *d_output; + int d_align; + int d_naligned; + + public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + fir_filter_with_buffer_ccf(const std::vector<float> &taps); + + ~fir_filter_with_buffer_ccf(); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input is a single input value of the filter type + * + * \returns the filtered input value. + */ + gr_complex filter(gr_complex input); + + /*! + * \brief compute a single output value; designed for decimating filters. + * + * \p input is a single input value of the filter type. The value of dec is the + * decimating value of the filter, so input[] must have dec valid values. + * The filter pushes dec number of items onto the circ. buffer before computing + * a single output. + * + * \returns the filtered input value. + */ + gr_complex filter(const gr_complex input[], unsigned long dec); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN(gr_complex output[], + const gr_complex input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec(gr_complex output[], const gr_complex input[], + unsigned long n, unsigned long decimate); + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned int ntaps() const { return d_ntaps; } + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps(const std::vector<float> &taps); + + /*! + * \return current taps + */ + std::vector<float> taps() const; + }; + + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FIR_FILTER_WITH_BUFFER_H */ diff --git a/gr-filter/include/filter/firdes.h b/gr-filter/include/filter/firdes.h new file mode 100644 index 0000000000..172563ea00 --- /dev/null +++ b/gr-filter/include/filter/firdes.h @@ -0,0 +1,378 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2008,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _FILTER_FIRDES_H_ +#define _FILTER_FIRDES_H_ + +#include <filter/api.h> +#include <vector> +#include <cmath> +#include <gr_complex.h> + +namespace gr { + namespace filter { + + /*! + * \brief Finite Impulse Response (FIR) filter design functions. + * \ingroup filter_design + */ + + class FILTER_API firdes { + public: + + enum win_type { + WIN_HAMMING = 0, // max attenuation 53 dB + WIN_HANN = 1, // max attenuation 44 dB + WIN_BLACKMAN = 2, // max attenuation 74 dB + WIN_RECTANGULAR = 3, + WIN_KAISER = 4, // max attenuation a function of beta, google it + WIN_BLACKMAN_hARRIS = 5, + WIN_BLACKMAN_HARRIS = 5, // alias for capitalization consistency + }; + + + // ... class methods ... + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<float> + low_pass(double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB required stopband attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuatin --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + low_pass_2(double gain, + double sampling_freq, + double cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + high_pass(double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + high_pass_2(double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<float> + band_pass(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_pass_2(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a complex band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<gr_complex> + complex_band_pass(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a complex band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<gr_complex> + complex_band_pass_2(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_reject(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_reject_2(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*!\brief design a Hilbert Transform Filter + * + * \p ntaps: Number of taps, must be odd + * \p window_type: What kind of window to use + * \p beta: Only used for Kaiser + */ + static std::vector<float> + hilbert(unsigned int ntaps = 19, + win_type windowtype = WIN_RECTANGULAR, + double beta = 6.76); + + /*! + * \brief design a Root Cosine FIR Filter (do we need a window?) + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p symbol rate: symbol rate, must be a factor of sample rate + * \p alpha: excess bandwidth factor + * \p ntaps: number of taps + */ + static std::vector<float> + root_raised_cosine(double gain, + double sampling_freq, + double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK) + double alpha, // Excess Bandwidth Factor + int ntaps); + + /*! + * \brief design a Gaussian filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p symbols per bit: symbol rate, must be a factor of sample rate + * \p ntaps: number of taps + */ + static std::vector<float> + gaussian(double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps); + + // window functions ... + static std::vector<float> window (win_type type, int ntaps, double beta); + + private: + static double bessi0(double x); + static void sanity_check_1f(double sampling_freq, double f1, + double transition_width); + static void sanity_check_2f(double sampling_freq, double f1, double f2, + double transition_width); + static void sanity_check_2f_c(double sampling_freq, double f1, double f2, + double transition_width); + + static int compute_ntaps(double sampling_freq, + double transition_width, + win_type window_type, double beta); + + static int compute_ntaps_windes(double sampling_freq, + double transition_width, + double attenuation_dB); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* _FILTER_FIRDES_H_ */ diff --git a/gr-filter/include/filter/fractional_interpolator_cc.h b/gr-filter/include/filter/fractional_interpolator_cc.h new file mode 100644 index 0000000000..bb0e18932e --- /dev/null +++ b/gr-filter/include/filter/fractional_interpolator_cc.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_CC_H +#define INCLUDED_FRACTIONAL_INTERPOLATOR_CC_H + +#include <filter/api.h> +#include <gr_block.h> + +namespace gr { + namespace filter { + + /*! + * \brief Interpolating MMSE filter with complex input, complex output + * \ingroup filter_blk + */ + class FILTER_API fractional_interpolator_cc : virtual public gr_block + { + public: + // gr::filter::fractional_interpolator_cc::sptr + typedef boost::shared_ptr<fractional_interpolator_cc> sptr; + + /*! + * \brief Build the interpolating MMSE filter (complex input, complex output) + * + * \param phase_shift The phase shift of the output signal to the input + * \param interp_ratio The interpolation ratio = input_rate / output_rate. + */ + static sptr make(float phase_shift, + float interp_ratio); + + virtual float mu() const = 0; + virtual float interp_ratio() const = 0; + virtual void set_mu (float mu) = 0; + virtual void set_interp_ratio(float interp_ratio) = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H */ diff --git a/gr-filter/include/filter/fractional_interpolator_ff.h b/gr-filter/include/filter/fractional_interpolator_ff.h new file mode 100644 index 0000000000..fc43c34570 --- /dev/null +++ b/gr-filter/include/filter/fractional_interpolator_ff.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H +#define INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H + +#include <filter/api.h> +#include <gr_block.h> + +namespace gr { + namespace filter { + + /*! + * \brief Interpolating MMSE filter with float input, float output + * \ingroup filter_blk + */ + class FILTER_API fractional_interpolator_ff : virtual public gr_block + { + public: + // gr::filter::fractional_interpolator_ff::sptr + typedef boost::shared_ptr<fractional_interpolator_ff> sptr; + + /*! + * \brief Build the interpolating MMSE filter (float input, float output) + * + * \param phase_shift The phase shift of the output signal to the input + * \param interp_ratio The interpolation ratio = input_rate / output_rate. + */ + static sptr make(float phase_shift, + float interp_ratio); + + virtual float mu() const = 0; + virtual float interp_ratio() const = 0; + virtual void set_mu (float mu) = 0; + virtual void set_interp_ratio(float interp_ratio) = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_FF_H */ diff --git a/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t b/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t new file mode 100644 index 0000000000..88e15f823d --- /dev/null +++ b/gr-filter/include/filter/freq_xlating_fir_filter_XXX.h.t @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * WARNING: This file is automatically generated by cmake. + * Any changes made to this file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/api.h> +#include <gr_sync_decimator.h> +#include <gr_rotator.h> + +namespace gr { + namespace filter { + + + /*! + * \brief FIR filter combined with frequency translation with + * @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * + * \ingroup filter_blk + * + * This class efficiently combines a frequency translation + * (typically "down conversion") with a FIR filter (typically + * low-pass) and decimation. It is ideally suited for a "channel + * selection filter" and can be efficiently used to select and + * decimate a narrow band signal out of wide bandwidth input. + * + * Uses a single input array to produce a single output array. + * Additional inputs and/or outputs are ignored. + */ + class FILTER_API @BASE_NAME@ : virtual public gr_sync_decimator + { + public: + // gr::filter::@BASE_NAME@::sptr + typedef boost::shared_ptr<@BASE_NAME@> sptr; + + /*! + * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output, and + * @TAP_TYPE@ taps that also frequency translates a signal from + * \p center_freq. + * + * Construct a FIR filter with the given taps and a composite + * frequency translation that shifts center_freq down to zero + * Hz. The frequency translation logically comes before the + * filtering operation. + * + * \param decimation set the integer decimation rate + * \param taps a vector/list of taps of type @TAP_TYPE@ + * \param center_freq Center frequency of signal to down convert from (Hz) + * \param sampling_freq Sampling rate of signal (in Hz) + */ + static sptr make(int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, + double sampling_freq); + + virtual void set_center_freq(double center_freq) = 0; + virtual double center_freq() const = 0; + + virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0; + virtual std::vector<@TAP_TYPE@> taps() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/general/gr_map_bb.h b/gr-filter/include/filter/hilbert_fc.h index 0a2f5a45f8..de7cd82b69 100644 --- a/gnuradio-core/src/lib/general/gr_map_bb.h +++ b/gr-filter/include/filter/hilbert_fc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2004,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,34 +19,35 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_MAP_BB_H -#define INCLUDED_GR_MAP_BB_H -#include <gr_core_api.h> -#include <gr_sync_block.h> - -class gr_map_bb; -typedef boost::shared_ptr<gr_map_bb> gr_map_bb_sptr; - -GR_CORE_API gr_map_bb_sptr gr_make_map_bb(const std::vector<int> &map); - -/*! - * \brief output[i] = map[input[i]] - * \ingroup coding_blk - */ +#ifndef INCLUDED_FILTER_HILBERT_FC_H +#define INCLUDED_FILTER_HILBERT_FC_H -class GR_CORE_API gr_map_bb : public gr_sync_block -{ - friend GR_CORE_API gr_map_bb_sptr gr_make_map_bb(const std::vector<int> &map); - - unsigned char d_map[0x100]; - - gr_map_bb(const std::vector<int> &map); - -public: - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* INCLUDED_GR_MAP_BB_H */ +#include <filter/api.h> +#include <gr_sync_block.h> +#include <gr_types.h> + +namespace gr { + namespace filter { + + class FILTER_API hilbert_fc : virtual public gr_sync_block + { + public: + // gr::filter::hilbert_fc::sptr + typedef boost::shared_ptr<hilbert_fc> sptr; + + /*! + * \brief Hilbert transformer. + * \ingroup filter_blk + * + * real output is input appropriately delayed. + * imaginary output is hilbert filtered (90 degree phase shift) + * version of input. + */ + static sptr make(unsigned int ntaps); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_HILBERT_FC_H */ diff --git a/gr-filter/include/filter/iir_filter.h b/gr-filter/include/filter/iir_filter.h new file mode 100644 index 0000000000..667acec358 --- /dev/null +++ b/gr-filter/include/filter/iir_filter.h @@ -0,0 +1,183 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_IIR_FILTER_H +#define INCLUDED_IIR_FILTER_H + +#include <filter/api.h> +#include <vector> +#include <stdexcept> + +namespace gr { + namespace filter { + namespace kernel { + + /*! + * \brief base class template for Infinite Impulse Response filter (IIR) + */ + template<class i_type, class o_type, class tap_type> + class iir_filter + { + public: + /*! + * \brief Construct an IIR with the given taps. + * + * This filter uses the Direct Form I implementation, where + * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones. + * + * \p fftaps and \p fbtaps must have equal numbers of taps + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{\sum_{k=0}^{N} b_k z^{-k}}{1 - \sum_{k=1}^{M} a_k z^{-k}} + \f] + + * Note that some texts define the system function with a + in + * the denominator. If you're using that convention, you'll + * need to negate the feedback taps. + */ + iir_filter(const std::vector<tap_type>& fftaps, + const std::vector<tap_type>& fbtaps) throw (std::invalid_argument) + { + set_taps(fftaps, fbtaps); + } + + iir_filter() : d_latest_n(0),d_latest_m(0) { } + + ~iir_filter() {} + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter(const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have N valid entries. + */ + void filter_n(o_type output[], const i_type input[], long n); + + /*! + * \return number of taps in filter. + */ + unsigned ntaps_ff() const { return d_fftaps.size(); } + unsigned ntaps_fb() const { return d_fbtaps.size(); } + + /*! + * \brief install new taps. + */ + void set_taps(const std::vector<tap_type> &fftaps, + const std::vector<tap_type> &fbtaps) throw (std::invalid_argument) + { + d_latest_n = 0; + d_latest_m = 0; + d_fftaps = fftaps; + d_fbtaps = fbtaps; + + int n = fftaps.size(); + int m = fbtaps.size(); + d_prev_input.resize(2 * n); + d_prev_output.resize(2 * m); + + for(int i = 0; i < 2 * n; i++) { + d_prev_input[i] = 0; + } + for(int i = 0; i < 2 * m; i++) { + d_prev_output[i] = 0; + } + } + + protected: + std::vector<tap_type> d_fftaps; + std::vector<tap_type> d_fbtaps; + int d_latest_n; + int d_latest_m; + std::vector<tap_type> d_prev_output; + std::vector<i_type> d_prev_input; + }; + + // + // general case. We may want to specialize this + // + template<class i_type, class o_type, class tap_type> + o_type + iir_filter<i_type, o_type, tap_type>::filter(const i_type input) + { + tap_type acc; + unsigned i = 0; + unsigned n = ntaps_ff(); + unsigned m = ntaps_fb(); + + if(n == 0) + return (o_type)0; + + int latest_n = d_latest_n; + int latest_m = d_latest_m; + + acc = d_fftaps[0] * input; + for(i = 1; i < n; i ++) + acc += (d_fftaps[i] * d_prev_input[latest_n + i]); + for(i = 1; i < m; i ++) + acc += (d_fbtaps[i] * d_prev_output[latest_m + i]); + + // store the values twice to avoid having to handle wrap-around in the loop + d_prev_output[latest_m] = acc; + d_prev_output[latest_m+m] = acc; + d_prev_input[latest_n] = input; + d_prev_input[latest_n+n] = input; + + latest_n--; + latest_m--; + if(latest_n < 0) + latest_n += n; + if(latest_m < 0) + latest_m += m; + + d_latest_m = latest_m; + d_latest_n = latest_n; + return (o_type)acc; + } + + template<class i_type, class o_type, class tap_type> + void + iir_filter<i_type, o_type, tap_type>::filter_n(o_type output[], + const i_type input[], + long n) + { + for(int i = 0; i < n; i++) + output[i] = filter(input[i]); + } + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_IIR_FILTER_H */ + diff --git a/gr-filter/include/filter/iir_filter_ffd.h b/gr-filter/include/filter/iir_filter_ffd.h new file mode 100644 index 0000000000..04dd1e7767 --- /dev/null +++ b/gr-filter/include/filter/iir_filter_ffd.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_IIR_FILTER_FFD_H +#define INCLUDED_IIR_FILTER_FFD_H + +#include <filter/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace filter { + + /*! + * \brief IIR filter with float input, float output and double taps + * \ingroup filter_blk + * + * This filter uses the Direct Form I implementation, where + * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones. + * + * + * The input and output satisfy a difference equation of the form + \htmlonly + \f{ + y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k] + \f} + \endhtmlonly + + \xmlonly + y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k] + \endxmlonly + + * with the corresponding rational system function + \htmlonly + \f{ + H(z) = \ frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}} + \f} + \endhtmlonly + + \xmlonly + H(z) = \ frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}} + \endxmlonly + + * Note that some texts define the system function with a + in the + * denominator. If you're using that convention, you'll need to + * negate the feedback taps. + */ + class FILTER_API iir_filter_ffd : virtual public gr_sync_block + { + public: + // gr::filter::iir_filter_ffd::sptr + typedef boost::shared_ptr<iir_filter_ffd> sptr; + + static sptr make(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps); + + virtual void set_taps(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_IIR_FILTER_FFD_H */ diff --git a/gr-filter/include/filter/interp_fir_filter_XXX.h.t b/gr-filter/include/filter/interp_fir_filter_XXX.h.t new file mode 100644 index 0000000000..b66c9f6439 --- /dev/null +++ b/gr-filter/include/filter/interp_fir_filter_XXX.h.t @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/api.h> +#include <gr_sync_interpolator.h> + +namespace gr { + namespace filter { + + /*! + * \brief Interpolating FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_blk + * + * The fir_filter_XXX blocks create finite impulse response + * (FIR) filters that perform the convolution in the time + * domain: + * + * \code + * out = 0 + * for i in ntaps: + * out += input[n-i] * taps[i] + * \endcode + * + * The taps are a C++ vector (or Python list) of values of the + * type specified by the third letter in the block's suffix. For + * this block, the value is of type @TAP_TYPE@. Taps can be + * created using the firdes or optfir tools. + * + * These versions of the filter can also act as up-samplers + * (or interpolators) by specifying an integer value for \p + * interpolation. + * + */ + class FILTER_API @BASE_NAME@ : virtual public gr_sync_interpolator + { + public: + // gr::filter::@BASE_NAME@::sptr + typedef boost::shared_ptr<@BASE_NAME@> sptr; + + /*! + * \brief Interpolating FIR filter with @I_TYPE@ input, @O_TYPE@ output, and @TAP_TYPE@ taps + * \ingroup filter_blk + * + * \param interpolation set the integer interpolation rate + * \param taps a vector/list of taps of type @TAP_TYPE@ + */ + static sptr make(unsigned interpolation, + const std::vector<@TAP_TYPE@> &taps); + + virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0; + virtual std::vector<@TAP_TYPE@> taps() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/include/filter/interpolator_taps.h b/gr-filter/include/filter/interpolator_taps.h new file mode 100644 index 0000000000..a232edd384 --- /dev/null +++ b/gr-filter/include/filter/interpolator_taps.h @@ -0,0 +1,140 @@ +/* + * This file was machine generated by gen_interpolator_taps. + * DO NOT EDIT BY HAND. + */ + +static const int NTAPS = 8; +static const int NSTEPS = 128; + +static const float taps[NSTEPS+1][NTAPS] = { + // -4 -3 -2 -1 0 1 2 3 mu + { 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 0/128 + { -1.54700e-04, 8.53777e-04, -2.76968e-03, 7.89295e-03, 9.98534e-01, -5.41054e-03, 1.24642e-03, -1.98993e-04 }, // 1/128 + { -3.09412e-04, 1.70888e-03, -5.55134e-03, 1.58840e-02, 9.96891e-01, -1.07209e-02, 2.47942e-03, -3.96391e-04 }, // 2/128 + { -4.64053e-04, 2.56486e-03, -8.34364e-03, 2.39714e-02, 9.95074e-01, -1.59305e-02, 3.69852e-03, -5.92100e-04 }, // 3/128 + { -6.18544e-04, 3.42130e-03, -1.11453e-02, 3.21531e-02, 9.93082e-01, -2.10389e-02, 4.90322e-03, -7.86031e-04 }, // 4/128 + { -7.72802e-04, 4.27773e-03, -1.39548e-02, 4.04274e-02, 9.90917e-01, -2.60456e-02, 6.09305e-03, -9.78093e-04 }, // 5/128 + { -9.26747e-04, 5.13372e-03, -1.67710e-02, 4.87921e-02, 9.88580e-01, -3.09503e-02, 7.26755e-03, -1.16820e-03 }, // 6/128 + { -1.08030e-03, 5.98883e-03, -1.95925e-02, 5.72454e-02, 9.86071e-01, -3.57525e-02, 8.42626e-03, -1.35627e-03 }, // 7/128 + { -1.23337e-03, 6.84261e-03, -2.24178e-02, 6.57852e-02, 9.83392e-01, -4.04519e-02, 9.56876e-03, -1.54221e-03 }, // 8/128 + { -1.38589e-03, 7.69462e-03, -2.52457e-02, 7.44095e-02, 9.80543e-01, -4.50483e-02, 1.06946e-02, -1.72594e-03 }, // 9/128 + { -1.53777e-03, 8.54441e-03, -2.80746e-02, 8.31162e-02, 9.77526e-01, -4.95412e-02, 1.18034e-02, -1.90738e-03 }, // 10/128 + { -1.68894e-03, 9.39154e-03, -3.09033e-02, 9.19033e-02, 9.74342e-01, -5.39305e-02, 1.28947e-02, -2.08645e-03 }, // 11/128 + { -1.83931e-03, 1.02356e-02, -3.37303e-02, 1.00769e-01, 9.70992e-01, -5.82159e-02, 1.39681e-02, -2.26307e-03 }, // 12/128 + { -1.98880e-03, 1.10760e-02, -3.65541e-02, 1.09710e-01, 9.67477e-01, -6.23972e-02, 1.50233e-02, -2.43718e-03 }, // 13/128 + { -2.13733e-03, 1.19125e-02, -3.93735e-02, 1.18725e-01, 9.63798e-01, -6.64743e-02, 1.60599e-02, -2.60868e-03 }, // 14/128 + { -2.28483e-03, 1.27445e-02, -4.21869e-02, 1.27812e-01, 9.59958e-01, -7.04471e-02, 1.70776e-02, -2.77751e-03 }, // 15/128 + { -2.43121e-03, 1.35716e-02, -4.49929e-02, 1.36968e-01, 9.55956e-01, -7.43154e-02, 1.80759e-02, -2.94361e-03 }, // 16/128 + { -2.57640e-03, 1.43934e-02, -4.77900e-02, 1.46192e-01, 9.51795e-01, -7.80792e-02, 1.90545e-02, -3.10689e-03 }, // 17/128 + { -2.72032e-03, 1.52095e-02, -5.05770e-02, 1.55480e-01, 9.47477e-01, -8.17385e-02, 2.00132e-02, -3.26730e-03 }, // 18/128 + { -2.86289e-03, 1.60193e-02, -5.33522e-02, 1.64831e-01, 9.43001e-01, -8.52933e-02, 2.09516e-02, -3.42477e-03 }, // 19/128 + { -3.00403e-03, 1.68225e-02, -5.61142e-02, 1.74242e-01, 9.38371e-01, -8.87435e-02, 2.18695e-02, -3.57923e-03 }, // 20/128 + { -3.14367e-03, 1.76185e-02, -5.88617e-02, 1.83711e-01, 9.33586e-01, -9.20893e-02, 2.27664e-02, -3.73062e-03 }, // 21/128 + { -3.28174e-03, 1.84071e-02, -6.15931e-02, 1.93236e-01, 9.28650e-01, -9.53307e-02, 2.36423e-02, -3.87888e-03 }, // 22/128 + { -3.41815e-03, 1.91877e-02, -6.43069e-02, 2.02814e-01, 9.23564e-01, -9.84679e-02, 2.44967e-02, -4.02397e-03 }, // 23/128 + { -3.55283e-03, 1.99599e-02, -6.70018e-02, 2.12443e-01, 9.18329e-01, -1.01501e-01, 2.53295e-02, -4.16581e-03 }, // 24/128 + { -3.68570e-03, 2.07233e-02, -6.96762e-02, 2.22120e-01, 9.12947e-01, -1.04430e-01, 2.61404e-02, -4.30435e-03 }, // 25/128 + { -3.81671e-03, 2.14774e-02, -7.23286e-02, 2.31843e-01, 9.07420e-01, -1.07256e-01, 2.69293e-02, -4.43955e-03 }, // 26/128 + { -3.94576e-03, 2.22218e-02, -7.49577e-02, 2.41609e-01, 9.01749e-01, -1.09978e-01, 2.76957e-02, -4.57135e-03 }, // 27/128 + { -4.07279e-03, 2.29562e-02, -7.75620e-02, 2.51417e-01, 8.95936e-01, -1.12597e-01, 2.84397e-02, -4.69970e-03 }, // 28/128 + { -4.19774e-03, 2.36801e-02, -8.01399e-02, 2.61263e-01, 8.89984e-01, -1.15113e-01, 2.91609e-02, -4.82456e-03 }, // 29/128 + { -4.32052e-03, 2.43930e-02, -8.26900e-02, 2.71144e-01, 8.83893e-01, -1.17526e-01, 2.98593e-02, -4.94589e-03 }, // 30/128 + { -4.44107e-03, 2.50946e-02, -8.52109e-02, 2.81060e-01, 8.77666e-01, -1.19837e-01, 3.05345e-02, -5.06363e-03 }, // 31/128 + { -4.55932e-03, 2.57844e-02, -8.77011e-02, 2.91006e-01, 8.71305e-01, -1.22047e-01, 3.11866e-02, -5.17776e-03 }, // 32/128 + { -4.67520e-03, 2.64621e-02, -9.01591e-02, 3.00980e-01, 8.64812e-01, -1.24154e-01, 3.18153e-02, -5.28823e-03 }, // 33/128 + { -4.78866e-03, 2.71272e-02, -9.25834e-02, 3.10980e-01, 8.58189e-01, -1.26161e-01, 3.24205e-02, -5.39500e-03 }, // 34/128 + { -4.89961e-03, 2.77794e-02, -9.49727e-02, 3.21004e-01, 8.51437e-01, -1.28068e-01, 3.30021e-02, -5.49804e-03 }, // 35/128 + { -5.00800e-03, 2.84182e-02, -9.73254e-02, 3.31048e-01, 8.44559e-01, -1.29874e-01, 3.35600e-02, -5.59731e-03 }, // 36/128 + { -5.11376e-03, 2.90433e-02, -9.96402e-02, 3.41109e-01, 8.37557e-01, -1.31581e-01, 3.40940e-02, -5.69280e-03 }, // 37/128 + { -5.21683e-03, 2.96543e-02, -1.01915e-01, 3.51186e-01, 8.30432e-01, -1.33189e-01, 3.46042e-02, -5.78446e-03 }, // 38/128 + { -5.31716e-03, 3.02507e-02, -1.04150e-01, 3.61276e-01, 8.23188e-01, -1.34699e-01, 3.50903e-02, -5.87227e-03 }, // 39/128 + { -5.41467e-03, 3.08323e-02, -1.06342e-01, 3.71376e-01, 8.15826e-01, -1.36111e-01, 3.55525e-02, -5.95620e-03 }, // 40/128 + { -5.50931e-03, 3.13987e-02, -1.08490e-01, 3.81484e-01, 8.08348e-01, -1.37426e-01, 3.59905e-02, -6.03624e-03 }, // 41/128 + { -5.60103e-03, 3.19495e-02, -1.10593e-01, 3.91596e-01, 8.00757e-01, -1.38644e-01, 3.64044e-02, -6.11236e-03 }, // 42/128 + { -5.68976e-03, 3.24843e-02, -1.12650e-01, 4.01710e-01, 7.93055e-01, -1.39767e-01, 3.67941e-02, -6.18454e-03 }, // 43/128 + { -5.77544e-03, 3.30027e-02, -1.14659e-01, 4.11823e-01, 7.85244e-01, -1.40794e-01, 3.71596e-02, -6.25277e-03 }, // 44/128 + { -5.85804e-03, 3.35046e-02, -1.16618e-01, 4.21934e-01, 7.77327e-01, -1.41727e-01, 3.75010e-02, -6.31703e-03 }, // 45/128 + { -5.93749e-03, 3.39894e-02, -1.18526e-01, 4.32038e-01, 7.69305e-01, -1.42566e-01, 3.78182e-02, -6.37730e-03 }, // 46/128 + { -6.01374e-03, 3.44568e-02, -1.20382e-01, 4.42134e-01, 7.61181e-01, -1.43313e-01, 3.81111e-02, -6.43358e-03 }, // 47/128 + { -6.08674e-03, 3.49066e-02, -1.22185e-01, 4.52218e-01, 7.52958e-01, -1.43968e-01, 3.83800e-02, -6.48585e-03 }, // 48/128 + { -6.15644e-03, 3.53384e-02, -1.23933e-01, 4.62289e-01, 7.44637e-01, -1.44531e-01, 3.86247e-02, -6.53412e-03 }, // 49/128 + { -6.22280e-03, 3.57519e-02, -1.25624e-01, 4.72342e-01, 7.36222e-01, -1.45004e-01, 3.88454e-02, -6.57836e-03 }, // 50/128 + { -6.28577e-03, 3.61468e-02, -1.27258e-01, 4.82377e-01, 7.27714e-01, -1.45387e-01, 3.90420e-02, -6.61859e-03 }, // 51/128 + { -6.34530e-03, 3.65227e-02, -1.28832e-01, 4.92389e-01, 7.19116e-01, -1.45682e-01, 3.92147e-02, -6.65479e-03 }, // 52/128 + { -6.40135e-03, 3.68795e-02, -1.30347e-01, 5.02377e-01, 7.10431e-01, -1.45889e-01, 3.93636e-02, -6.68698e-03 }, // 53/128 + { -6.45388e-03, 3.72167e-02, -1.31800e-01, 5.12337e-01, 7.01661e-01, -1.46009e-01, 3.94886e-02, -6.71514e-03 }, // 54/128 + { -6.50285e-03, 3.75341e-02, -1.33190e-01, 5.22267e-01, 6.92808e-01, -1.46043e-01, 3.95900e-02, -6.73929e-03 }, // 55/128 + { -6.54823e-03, 3.78315e-02, -1.34515e-01, 5.32164e-01, 6.83875e-01, -1.45993e-01, 3.96678e-02, -6.75943e-03 }, // 56/128 + { -6.58996e-03, 3.81085e-02, -1.35775e-01, 5.42025e-01, 6.74865e-01, -1.45859e-01, 3.97222e-02, -6.77557e-03 }, // 57/128 + { -6.62802e-03, 3.83650e-02, -1.36969e-01, 5.51849e-01, 6.65779e-01, -1.45641e-01, 3.97532e-02, -6.78771e-03 }, // 58/128 + { -6.66238e-03, 3.86006e-02, -1.38094e-01, 5.61631e-01, 6.56621e-01, -1.45343e-01, 3.97610e-02, -6.79588e-03 }, // 59/128 + { -6.69300e-03, 3.88151e-02, -1.39150e-01, 5.71370e-01, 6.47394e-01, -1.44963e-01, 3.97458e-02, -6.80007e-03 }, // 60/128 + { -6.71985e-03, 3.90083e-02, -1.40136e-01, 5.81063e-01, 6.38099e-01, -1.44503e-01, 3.97077e-02, -6.80032e-03 }, // 61/128 + { -6.74291e-03, 3.91800e-02, -1.41050e-01, 5.90706e-01, 6.28739e-01, -1.43965e-01, 3.96469e-02, -6.79662e-03 }, // 62/128 + { -6.76214e-03, 3.93299e-02, -1.41891e-01, 6.00298e-01, 6.19318e-01, -1.43350e-01, 3.95635e-02, -6.78902e-03 }, // 63/128 + { -6.77751e-03, 3.94578e-02, -1.42658e-01, 6.09836e-01, 6.09836e-01, -1.42658e-01, 3.94578e-02, -6.77751e-03 }, // 64/128 + { -6.78902e-03, 3.95635e-02, -1.43350e-01, 6.19318e-01, 6.00298e-01, -1.41891e-01, 3.93299e-02, -6.76214e-03 }, // 65/128 + { -6.79662e-03, 3.96469e-02, -1.43965e-01, 6.28739e-01, 5.90706e-01, -1.41050e-01, 3.91800e-02, -6.74291e-03 }, // 66/128 + { -6.80032e-03, 3.97077e-02, -1.44503e-01, 6.38099e-01, 5.81063e-01, -1.40136e-01, 3.90083e-02, -6.71985e-03 }, // 67/128 + { -6.80007e-03, 3.97458e-02, -1.44963e-01, 6.47394e-01, 5.71370e-01, -1.39150e-01, 3.88151e-02, -6.69300e-03 }, // 68/128 + { -6.79588e-03, 3.97610e-02, -1.45343e-01, 6.56621e-01, 5.61631e-01, -1.38094e-01, 3.86006e-02, -6.66238e-03 }, // 69/128 + { -6.78771e-03, 3.97532e-02, -1.45641e-01, 6.65779e-01, 5.51849e-01, -1.36969e-01, 3.83650e-02, -6.62802e-03 }, // 70/128 + { -6.77557e-03, 3.97222e-02, -1.45859e-01, 6.74865e-01, 5.42025e-01, -1.35775e-01, 3.81085e-02, -6.58996e-03 }, // 71/128 + { -6.75943e-03, 3.96678e-02, -1.45993e-01, 6.83875e-01, 5.32164e-01, -1.34515e-01, 3.78315e-02, -6.54823e-03 }, // 72/128 + { -6.73929e-03, 3.95900e-02, -1.46043e-01, 6.92808e-01, 5.22267e-01, -1.33190e-01, 3.75341e-02, -6.50285e-03 }, // 73/128 + { -6.71514e-03, 3.94886e-02, -1.46009e-01, 7.01661e-01, 5.12337e-01, -1.31800e-01, 3.72167e-02, -6.45388e-03 }, // 74/128 + { -6.68698e-03, 3.93636e-02, -1.45889e-01, 7.10431e-01, 5.02377e-01, -1.30347e-01, 3.68795e-02, -6.40135e-03 }, // 75/128 + { -6.65479e-03, 3.92147e-02, -1.45682e-01, 7.19116e-01, 4.92389e-01, -1.28832e-01, 3.65227e-02, -6.34530e-03 }, // 76/128 + { -6.61859e-03, 3.90420e-02, -1.45387e-01, 7.27714e-01, 4.82377e-01, -1.27258e-01, 3.61468e-02, -6.28577e-03 }, // 77/128 + { -6.57836e-03, 3.88454e-02, -1.45004e-01, 7.36222e-01, 4.72342e-01, -1.25624e-01, 3.57519e-02, -6.22280e-03 }, // 78/128 + { -6.53412e-03, 3.86247e-02, -1.44531e-01, 7.44637e-01, 4.62289e-01, -1.23933e-01, 3.53384e-02, -6.15644e-03 }, // 79/128 + { -6.48585e-03, 3.83800e-02, -1.43968e-01, 7.52958e-01, 4.52218e-01, -1.22185e-01, 3.49066e-02, -6.08674e-03 }, // 80/128 + { -6.43358e-03, 3.81111e-02, -1.43313e-01, 7.61181e-01, 4.42134e-01, -1.20382e-01, 3.44568e-02, -6.01374e-03 }, // 81/128 + { -6.37730e-03, 3.78182e-02, -1.42566e-01, 7.69305e-01, 4.32038e-01, -1.18526e-01, 3.39894e-02, -5.93749e-03 }, // 82/128 + { -6.31703e-03, 3.75010e-02, -1.41727e-01, 7.77327e-01, 4.21934e-01, -1.16618e-01, 3.35046e-02, -5.85804e-03 }, // 83/128 + { -6.25277e-03, 3.71596e-02, -1.40794e-01, 7.85244e-01, 4.11823e-01, -1.14659e-01, 3.30027e-02, -5.77544e-03 }, // 84/128 + { -6.18454e-03, 3.67941e-02, -1.39767e-01, 7.93055e-01, 4.01710e-01, -1.12650e-01, 3.24843e-02, -5.68976e-03 }, // 85/128 + { -6.11236e-03, 3.64044e-02, -1.38644e-01, 8.00757e-01, 3.91596e-01, -1.10593e-01, 3.19495e-02, -5.60103e-03 }, // 86/128 + { -6.03624e-03, 3.59905e-02, -1.37426e-01, 8.08348e-01, 3.81484e-01, -1.08490e-01, 3.13987e-02, -5.50931e-03 }, // 87/128 + { -5.95620e-03, 3.55525e-02, -1.36111e-01, 8.15826e-01, 3.71376e-01, -1.06342e-01, 3.08323e-02, -5.41467e-03 }, // 88/128 + { -5.87227e-03, 3.50903e-02, -1.34699e-01, 8.23188e-01, 3.61276e-01, -1.04150e-01, 3.02507e-02, -5.31716e-03 }, // 89/128 + { -5.78446e-03, 3.46042e-02, -1.33189e-01, 8.30432e-01, 3.51186e-01, -1.01915e-01, 2.96543e-02, -5.21683e-03 }, // 90/128 + { -5.69280e-03, 3.40940e-02, -1.31581e-01, 8.37557e-01, 3.41109e-01, -9.96402e-02, 2.90433e-02, -5.11376e-03 }, // 91/128 + { -5.59731e-03, 3.35600e-02, -1.29874e-01, 8.44559e-01, 3.31048e-01, -9.73254e-02, 2.84182e-02, -5.00800e-03 }, // 92/128 + { -5.49804e-03, 3.30021e-02, -1.28068e-01, 8.51437e-01, 3.21004e-01, -9.49727e-02, 2.77794e-02, -4.89961e-03 }, // 93/128 + { -5.39500e-03, 3.24205e-02, -1.26161e-01, 8.58189e-01, 3.10980e-01, -9.25834e-02, 2.71272e-02, -4.78866e-03 }, // 94/128 + { -5.28823e-03, 3.18153e-02, -1.24154e-01, 8.64812e-01, 3.00980e-01, -9.01591e-02, 2.64621e-02, -4.67520e-03 }, // 95/128 + { -5.17776e-03, 3.11866e-02, -1.22047e-01, 8.71305e-01, 2.91006e-01, -8.77011e-02, 2.57844e-02, -4.55932e-03 }, // 96/128 + { -5.06363e-03, 3.05345e-02, -1.19837e-01, 8.77666e-01, 2.81060e-01, -8.52109e-02, 2.50946e-02, -4.44107e-03 }, // 97/128 + { -4.94589e-03, 2.98593e-02, -1.17526e-01, 8.83893e-01, 2.71144e-01, -8.26900e-02, 2.43930e-02, -4.32052e-03 }, // 98/128 + { -4.82456e-03, 2.91609e-02, -1.15113e-01, 8.89984e-01, 2.61263e-01, -8.01399e-02, 2.36801e-02, -4.19774e-03 }, // 99/128 + { -4.69970e-03, 2.84397e-02, -1.12597e-01, 8.95936e-01, 2.51417e-01, -7.75620e-02, 2.29562e-02, -4.07279e-03 }, // 100/128 + { -4.57135e-03, 2.76957e-02, -1.09978e-01, 9.01749e-01, 2.41609e-01, -7.49577e-02, 2.22218e-02, -3.94576e-03 }, // 101/128 + { -4.43955e-03, 2.69293e-02, -1.07256e-01, 9.07420e-01, 2.31843e-01, -7.23286e-02, 2.14774e-02, -3.81671e-03 }, // 102/128 + { -4.30435e-03, 2.61404e-02, -1.04430e-01, 9.12947e-01, 2.22120e-01, -6.96762e-02, 2.07233e-02, -3.68570e-03 }, // 103/128 + { -4.16581e-03, 2.53295e-02, -1.01501e-01, 9.18329e-01, 2.12443e-01, -6.70018e-02, 1.99599e-02, -3.55283e-03 }, // 104/128 + { -4.02397e-03, 2.44967e-02, -9.84679e-02, 9.23564e-01, 2.02814e-01, -6.43069e-02, 1.91877e-02, -3.41815e-03 }, // 105/128 + { -3.87888e-03, 2.36423e-02, -9.53307e-02, 9.28650e-01, 1.93236e-01, -6.15931e-02, 1.84071e-02, -3.28174e-03 }, // 106/128 + { -3.73062e-03, 2.27664e-02, -9.20893e-02, 9.33586e-01, 1.83711e-01, -5.88617e-02, 1.76185e-02, -3.14367e-03 }, // 107/128 + { -3.57923e-03, 2.18695e-02, -8.87435e-02, 9.38371e-01, 1.74242e-01, -5.61142e-02, 1.68225e-02, -3.00403e-03 }, // 108/128 + { -3.42477e-03, 2.09516e-02, -8.52933e-02, 9.43001e-01, 1.64831e-01, -5.33522e-02, 1.60193e-02, -2.86289e-03 }, // 109/128 + { -3.26730e-03, 2.00132e-02, -8.17385e-02, 9.47477e-01, 1.55480e-01, -5.05770e-02, 1.52095e-02, -2.72032e-03 }, // 110/128 + { -3.10689e-03, 1.90545e-02, -7.80792e-02, 9.51795e-01, 1.46192e-01, -4.77900e-02, 1.43934e-02, -2.57640e-03 }, // 111/128 + { -2.94361e-03, 1.80759e-02, -7.43154e-02, 9.55956e-01, 1.36968e-01, -4.49929e-02, 1.35716e-02, -2.43121e-03 }, // 112/128 + { -2.77751e-03, 1.70776e-02, -7.04471e-02, 9.59958e-01, 1.27812e-01, -4.21869e-02, 1.27445e-02, -2.28483e-03 }, // 113/128 + { -2.60868e-03, 1.60599e-02, -6.64743e-02, 9.63798e-01, 1.18725e-01, -3.93735e-02, 1.19125e-02, -2.13733e-03 }, // 114/128 + { -2.43718e-03, 1.50233e-02, -6.23972e-02, 9.67477e-01, 1.09710e-01, -3.65541e-02, 1.10760e-02, -1.98880e-03 }, // 115/128 + { -2.26307e-03, 1.39681e-02, -5.82159e-02, 9.70992e-01, 1.00769e-01, -3.37303e-02, 1.02356e-02, -1.83931e-03 }, // 116/128 + { -2.08645e-03, 1.28947e-02, -5.39305e-02, 9.74342e-01, 9.19033e-02, -3.09033e-02, 9.39154e-03, -1.68894e-03 }, // 117/128 + { -1.90738e-03, 1.18034e-02, -4.95412e-02, 9.77526e-01, 8.31162e-02, -2.80746e-02, 8.54441e-03, -1.53777e-03 }, // 118/128 + { -1.72594e-03, 1.06946e-02, -4.50483e-02, 9.80543e-01, 7.44095e-02, -2.52457e-02, 7.69462e-03, -1.38589e-03 }, // 119/128 + { -1.54221e-03, 9.56876e-03, -4.04519e-02, 9.83392e-01, 6.57852e-02, -2.24178e-02, 6.84261e-03, -1.23337e-03 }, // 120/128 + { -1.35627e-03, 8.42626e-03, -3.57525e-02, 9.86071e-01, 5.72454e-02, -1.95925e-02, 5.98883e-03, -1.08030e-03 }, // 121/128 + { -1.16820e-03, 7.26755e-03, -3.09503e-02, 9.88580e-01, 4.87921e-02, -1.67710e-02, 5.13372e-03, -9.26747e-04 }, // 122/128 + { -9.78093e-04, 6.09305e-03, -2.60456e-02, 9.90917e-01, 4.04274e-02, -1.39548e-02, 4.27773e-03, -7.72802e-04 }, // 123/128 + { -7.86031e-04, 4.90322e-03, -2.10389e-02, 9.93082e-01, 3.21531e-02, -1.11453e-02, 3.42130e-03, -6.18544e-04 }, // 124/128 + { -5.92100e-04, 3.69852e-03, -1.59305e-02, 9.95074e-01, 2.39714e-02, -8.34364e-03, 2.56486e-03, -4.64053e-04 }, // 125/128 + { -3.96391e-04, 2.47942e-03, -1.07209e-02, 9.96891e-01, 1.58840e-02, -5.55134e-03, 1.70888e-03, -3.09412e-04 }, // 126/128 + { -1.98993e-04, 1.24642e-03, -5.41054e-03, 9.98534e-01, 7.89295e-03, -2.76968e-03, 8.53777e-04, -1.54700e-04 }, // 127/128 + { 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 128/128 +}; diff --git a/gr-filter/include/filter/mmse_fir_interpolator_cc.h b/gr-filter/include/filter/mmse_fir_interpolator_cc.h new file mode 100644 index 0000000000..0436b4a0ff --- /dev/null +++ b/gr-filter/include/filter/mmse_fir_interpolator_cc.h @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ + +#include <filter/api.h> +#include <filter/fir_filter.h> +#include <gr_complex.h> +#include <vector> + +namespace gr { + namespace filter { + + /*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * \ingroup filter_primitive + * + * This implements a Mininum Mean Squared Error interpolator with + * 8 taps. It is suitable for signals where the bandwidth of + * interest B = 1/(4*Ts) Where Ts is the time between samples. + * + * Although mu, the fractional delay, is specified as a float, it + * is actually quantized. 0.0 <= mu <= 1.0. That is, mu is + * quantized in the interpolate method to 32nd's of a sample. + * + * For more information, in the GNU Radio source code, see: + * \li gnuradio-core/src/gen_interpolator_taps/README + * \li gnuradio-core/src/gen_interpolator_taps/praxis.txt + */ + + class FILTER_API mmse_fir_interpolator_cc + { + public: + mmse_fir_interpolator_cc(); + ~mmse_fir_interpolator_cc(); + + unsigned ntaps() const; + unsigned nsteps() const; + + /*! + * \brief compute a single interpolated output value. + * + * \p input must have ntaps() valid entries and be 8-byte aligned. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * \throws std::invalid_argument if input is not 8-byte aligned. + * + * \p mu must be in the range [0, 1] and specifies the fractional delay. + * + * \returns the interpolated input value. + */ + gr_complex interpolate(const gr_complex input[], float mu) const; + + protected: + std::vector<kernel::fir_filter_ccf *> filters; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* _MMSE_FIR_INTERPOLATOR_CC_H_ */ diff --git a/gr-filter/include/filter/mmse_fir_interpolator_ff.h b/gr-filter/include/filter/mmse_fir_interpolator_ff.h new file mode 100644 index 0000000000..4353aa94f1 --- /dev/null +++ b/gr-filter/include/filter/mmse_fir_interpolator_ff.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _MMSE_FIR_INTERPOLATOR_FF_H_ +#define _MMSE_FIR_INTERPOLATOR_FF_H_ + +#include <filter/api.h> +#include <filter/fir_filter.h> +#include <vector> + +namespace gr { + namespace filter { + + /*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * \ingroup filter_primitive + * + * This implements a Mininum Mean Squared Error interpolator with + * 8 taps. It is suitable for signals where the bandwidth of + * interest B = 1/(4*Ts) Where Ts is the time between samples. + * + * Although mu, the fractional delay, is specified as a float, it + * is actually quantized. 0.0 <= mu <= 1.0. That is, mu is + * quantized in the interpolate method to 32nd's of a sample. + * + * For more information, in the GNU Radio source code, see: + * \li gnuradio-core/src/gen_interpolator_taps/README + * \li gnuradio-core/src/gen_interpolator_taps/praxis.txt + */ + class FILTER_API mmse_fir_interpolator_ff + { + public: + mmse_fir_interpolator_ff(); + ~mmse_fir_interpolator_ff(); + + unsigned ntaps() const; + unsigned nsteps() const; + + /*! + * \brief compute a single interpolated output value. + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \p mu must be in the range [0, 1] and specifies the fractional delay. + * + * \returns the interpolated input value. + */ + float interpolate(const float input[], float mu) const; + + protected: + std::vector<kernel::fir_filter_fff*> filters; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* _MMSE_FIR_INTERPOLATOR_FF_H_ */ diff --git a/gr-filter/include/filter/pfb_arb_resampler_ccf.h b/gr-filter/include/filter/pfb_arb_resampler_ccf.h new file mode 100644 index 0000000000..a154e055a0 --- /dev/null +++ b/gr-filter/include/filter/pfb_arb_resampler_ccf.h @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_ARB_RESAMPLER_CCF_H +#define INCLUDED_PFB_ARB_RESAMPLER_CCF_H + +#include <filter/api.h> +#include <gr_block.h> + +namespace gr { + namespace filter { + + /*! + * \class pfb_arb_resampler_ccf + * + * \brief Polyphase filterbank arbitrary resampler with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs arbitrary + * resampling. The resampling rate can be any real number + * <EM>r</EM>. The resampling is done by constructing <EM>N</EM> + * filters where <EM>N</EM> is the interpolation rate. We then + * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. + * + * Using <EM>N</EM> and <EM>D</EM>, we can perform rational + * resampling where <EM>N/D</EM> is a rational number close to the + * input rate <EM>r</EM> where we have <EM>N</EM> filters and we + * cycle through them as a polyphase filterbank with a stride of + * <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>. + * + * To get the arbitrary rate, we want to interpolate between two + * points. For each value out, we take an output from the current + * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then + * linearly interpolate between the two based on the real + * resampling rate we want. + * + * The linear interpolation only provides us with an approximation + * to the real sampling rate specified. The error is a + * quantization error between the two filters we used as our + * interpolation points. To this end, the number of filters, + * <EM>N</EM>, used determines the quantization error; the larger + * <EM>N</EM>, the smaller the noise. You can design for a + * specified noise floor by setting the filter size (parameters + * <EM>filter_size</EM>). The size defaults to 32 filters, which + * is about as good as most implementations need. + * + * The trick with designing this filter is in how to specify the + * taps of the prototype filter. Like the PFB interpolator, the + * taps are specified using the interpolated filter rate. In this + * case, that rate is the input sample rate multiplied by the + * number of filters in the filterbank, which is also the + * interpolation rate. All other values should be relative to this + * rate. + * + * For example, for a 32-filter arbitrary resampler and using the + * GNU Radio's firdes utility to build the filter, we build a + * low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB + * bandwidth of <EM>BW</EM> and a transition bandwidth of + * <EM>TB</EM>. We can also specify the out-of-band attenuation to + * use, <EM>ATT</EM>, and the filter window function (a + * Blackman-harris window in this case). The first input is the + * gain of the filter, which we specify here as the interpolation + * rate (<EM>32</EM>). + * + * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB, + * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The theory behind this block can be found in Chapter 7.5 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + + class FILTER_API pfb_arb_resampler_ccf : virtual public gr_block + { + public: + // gr::filter::pfb_arb_resampler_ccf::sptr + typedef boost::shared_ptr<pfb_arb_resampler_ccf> sptr; + + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + * related to quantization noise introduced during the resampling. + * Defaults to 32 filters. + */ + static sptr make(float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + + /*! + * Sets the resampling rate of the block. + */ + virtual void set_rate (float rate) = 0; + + /*! + * Sets the current phase offset in radians (0 to 2pi). + */ + virtual void set_phase(float ph) = 0; + + /*! + * Gets the current phase of the resampler in radians (2 to 2pi). + */ + virtual float phase() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_ARB_RESAMPLER_CCF_H */ diff --git a/gr-filter/include/filter/pfb_arb_resampler_fff.h b/gr-filter/include/filter/pfb_arb_resampler_fff.h new file mode 100644 index 0000000000..38dcc7132b --- /dev/null +++ b/gr-filter/include/filter/pfb_arb_resampler_fff.h @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_ARB_RESAMPLER_FFF_H +#define INCLUDED_PFB_ARB_RESAMPLER_FFF_H + +#include <filter/api.h> +#include <gr_block.h> + +namespace gr { + namespace filter { + + /*! + * \class pfb_arb_resampler_fff + * + * \brief Polyphase filterbank arbitrary resampler with + * float input, float output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs arbitrary + * resampling. The resampling rate can be any real number + * <EM>r</EM>. The resampling is done by constructing <EM>N</EM> + * filters where <EM>N</EM> is the interpolation rate. We then + * calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. + * + * Using <EM>N</EM> and <EM>D</EM>, we can perform rational + * resampling where <EM>N/D</EM> is a rational number close to the + * input rate <EM>r</EM> where we have <EM>N</EM> filters and we + * cycle through them as a polyphase filterbank with a stride of + * <EM>D</EM> so that <EM>i+1 = (i + D) % N</EM>. + * + * To get the arbitrary rate, we want to interpolate between two + * points. For each value out, we take an output from the current + * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then + * linearly interpolate between the two based on the real + * resampling rate we want. + * + * The linear interpolation only provides us with an approximation + * to the real sampling rate specified. The error is a + * quantization error between the two filters we used as our + * interpolation points. To this end, the number of filters, + * <EM>N</EM>, used determines the quantization error; the larger + * <EM>N</EM>, the smaller the noise. You can design for a + * specified noise floor by setting the filter size (parameters + * <EM>filter_size</EM>). The size defaults to 32 filters, which + * is about as good as most implementations need. + * + * The trick with designing this filter is in how to specify the + * taps of the prototype filter. Like the PFB interpolator, the + * taps are specified using the interpolated filter rate. In this + * case, that rate is the input sample rate multiplied by the + * number of filters in the filterbank, which is also the + * interpolation rate. All other values should be relative to this + * rate. + * + * For example, for a 32-filter arbitrary resampler and using the + * GNU Radio's firdes utility to build the filter, we build a + * low-pass filter with a sampling rate of <EM>fs</EM>, a 3-dB + * bandwidth of <EM>BW</EM> and a transition bandwidth of + * <EM>TB</EM>. We can also specify the out-of-band attenuation to + * use, <EM>ATT</EM>, and the filter window function (a + * Blackman-harris window in this case). The first input is the + * gain of the filter, which we specify here as the interpolation + * rate (<EM>32</EM>). + * + * <B><EM>self._taps = filter.firdes.low_pass_2(32, 32*fs, BW, TB, + * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The theory behind this block can be found in Chapter 7.5 of the + * following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + + class FILTER_API pfb_arb_resampler_fff : virtual public gr_block + { + public: + // gr::filter::pfb_arb_resampler_fff::sptr + typedef boost::shared_ptr<pfb_arb_resampler_fff> sptr; + + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + * related to quantization noise introduced during the resampling. + * Defaults to 32 filters. + */ + static sptr make(float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + + /*! + * Sets the resampling rate of the block. + */ + virtual void set_rate (float rate) = 0; + + /*! + * Sets the current phase offset in radians (0 to 2pi). + */ + virtual void set_phase(float ph) = 0; + + /*! + * Gets the current phase of the resampler in radians (2 to 2pi). + */ + virtual float phase() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_ARB_RESAMPLER_FFF_H */ diff --git a/gr-filter/include/filter/pfb_channelizer_ccf.h b/gr-filter/include/filter/pfb_channelizer_ccf.h new file mode 100644 index 0000000000..2ff83b5e7e --- /dev/null +++ b/gr-filter/include/filter/pfb_channelizer_ccf.h @@ -0,0 +1,204 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_FILTER_PFB_CHANNELIZER_CCF_H +#define INCLUDED_FILTER_PFB_CHANNELIZER_CCF_H + +#include <filter/api.h> +#include <gr_block.h> + +namespace gr { + namespace filter { + + /*! + * \class pfb_channelizer_ccf + * + * \brief Polyphase filterbank channelizer with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in complex inputs and channelizes it to <EM>M</EM> + * channels of equal bandwidth. Each of the resulting channels is + * decimated to the new rate that is the input sampling rate + * <EM>fs</EM> divided by the number of channels, <EM>M</EM>. + * + * The PFB channelizer code takes the taps generated above and builds + * a set of filters. The set contains <EM>M</EM> number of filters + * and each filter contains ceil(taps.size()/decim) number of taps. + * Each tap from the filter prototype is sequentially inserted into + * the next filter. When all of the input taps are used, the remaining + * filters in the filterbank are filled out with 0's to make sure each + * filter has the same number of taps. + * + * Each filter operates using the gr_fir filter classs of GNU Radio, + * which takes the input stream at <EM>i</EM> and performs the inner + * product calculation to <EM>i+(n-1)</EM> where <EM>n</EM> is the + * number of filter taps. To efficiently handle this in the GNU Radio + * structure, each filter input must come from its own input + * stream. So the channelizer must be provided with <EM>M</EM> streams + * where the input stream has been deinterleaved. This is most easily + * done using the gr_stream_to_streams block. + * + * The output is then produced as a vector, where index <EM>i</EM> in + * the vector is the next sample from the <EM>i</EM>th channel. This + * is most easily handled by sending the output to a + * gr_vector_to_streams block to handle the conversion and passing + * <EM>M</EM> streams out. + * + * The input and output formatting is done using a hier_block2 called + * pfb_channelizer_ccf. This can take in a single stream and outputs + * <EM>M</EM> streams based on the behavior described above. + * + * The filter's taps should be based on the input sampling rate. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, <EM>ATT</EM>, and the filter window + * function (a Blackman-harris window in this case). The first input + * is the gain of the filter, which we specify here as unity. + * + * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB, + * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The filter output can also be overs ampled. The over sampling rate + * is the ratio of the the actual output sampling rate to the normal + * output sampling rate. It must be rationally related to the number + * of channels as N/i for i in [1,N], which gives an outputsample rate + * of [fs/N, fs] where fs is the input sample rate and N is the number + * of channels. + * + * For example, for 6 channels with fs = 6000 Hz, the normal rate is + * 6000/6 = 1000 Hz. Allowable oversampling rates are 6/6, 6/5, 6/4, + * 6/3, 6/2, and 6/1 where the output sample rate of a 6/1 oversample + * ratio is 6000 Hz, or 6 times the normal 1000 Hz. A rate of 6/5 = 1.2, + * so the output rate would be 1200 Hz. + * + * The theory behind this block can be found in Chapter 6 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + * + */ + + class FILTER_API pfb_channelizer_ccf : virtual public gr_block + { + public: + // gr::filter::pfb_channelizer_ccf::sptr + typedef boost::shared_ptr<pfb_channelizer_ccf> sptr; + + /*! + * Build the polyphase filterbank decimator. + * \param numchans (unsigned integer) Specifies the number of + * channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter to + * populate the filterbank. + * \param oversample_rate (float) The over sampling rate is the + * ratio of the the actual output + * sampling rate to the normal + * output sampling rate. It must + * be rationally related to the + * number of channels as N/i for + * i in [1,N], which gives an + * outputsample rate of [fs/N, + * fs] where fs is the input + * sample rate and N is the + * number of channels. + * + * For example, for 6 channels + * with fs = 6000 Hz, the normal + * rateis 6000/6 = 1000 + * Hz. Allowable oversampling + * rates are 6/6, 6/5, 6/4, 6/3, + * 6/2, and 6/1 where the output + * sample rate of a 6/1 + * oversample ratio is 6000 Hz, + * or 6 times the normal 1000 Hz. + */ + static sptr make(unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Set the channel map. Channels are numbers as: + * + * N/2+1 | ... | N-1 | 0 | 1 | 2 | ... | N/2 + * <------------------- 0 --------------------> + * freq + * + * So output stream 0 comes from channel 0, etc. Setting a new + * channel map allows the user to specify which channel in frequency + * he/she wants to got to which output stream. + * + * The map should have the same number of elements as the number + * of output connections from the block. The minimum value of + * the map is 0 (for the 0th channel) and the maximum number is + * N-1 where N is the number of channels. + * + * We specify M as the number of output connections made where M + * <= N, so only M out of N channels are driven to an output + * stream. The number of items in the channel map should be at + * least M long. If there are more channels specified, any value + * in the map over M-1 will be ignored. If the size of the map + * is less than M the behavior is unknown (we don't wish to + * check every entry into the work function). + * + * This means that if the channelizer is splitting the signal up + * into N channels but only M channels are specified in the map + * (where M <= N), then M output streams must be connected and + * the map and the channel numbers used must be less than + * N-1. Output channel number can be reused, too. By default, + * the map is [0...M-1] with M = N. + */ + virtual void set_channel_map(const std::vector<int> &map) = 0; + + /*! + * Gets the current channel map. + */ + virtual std::vector<int> channel_map() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_PFB_CHANNELIZER_CCF_H */ diff --git a/gr-filter/include/filter/pfb_decimator_ccf.h b/gr-filter/include/filter/pfb_decimator_ccf.h new file mode 100644 index 0000000000..bf9d0d9508 --- /dev/null +++ b/gr-filter/include/filter/pfb_decimator_ccf.h @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_DECIMATOR_CCF_H +#define INCLUDED_PFB_DECIMATOR_CCF_H + +#include <filter/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace filter { + + /*! + * \class pfb_decimator_ccf + * \brief Polyphase filterbank bandpass decimator with gr_complex + * input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs interger down- + * sampling (decimation) with a polyphase filterbank. The first + * input is the integer specifying how much to decimate by. The + * second input is a vector (Python list) of floating-point taps + * of the prototype filter. The third input specifies the channel + * to extract. By default, the zeroth channel is used, which is + * the baseband channel (first Nyquist zone). + * + * The <EM>channel</EM> parameter specifies which channel to use + * since this class is capable of bandpass decimation. Given a + * complex input stream at a sampling rate of <EM>fs</EM> and a + * decimation rate of <EM>decim</EM>, the input frequency domain + * is split into <EM>decim</EM> channels that represent the + * Nyquist zones. Using the polyphase filterbank, we can select + * any one of these channels to decimate. + * + * The output signal will be the basebanded and decimated signal + * from that channel. This concept is very similar to the PFB + * channelizer (see #gr_pfb_channelizer_ccf) where only a single + * channel is extracted at a time. + * + * The filter's taps should be based on the sampling rate before + * decimation. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, <EM>ATT</EM>, and the filter window + * function (a Blackman-harris window in this case). The first + * input is the gain of the filter, which we specify here as + * unity. + * + * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB, + * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The PFB decimator code takes the taps generated above and + * builds a set of filters. The set contains <EM>decim</EM> number + * of filters and each filter contains ceil(taps.size()/decim) + * number of taps. Each tap from the filter prototype is + * sequentially inserted into the next filter. When all of the + * input taps are used, the remaining filters in the filterbank + * are filled out with 0's to make sure each filter has the same + * number of taps. + * + * The theory behind this block can be found in Chapter 6 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + + class FILTER_API pfb_decimator_ccf : virtual public gr_sync_block + { + public: + // gr::filter::pfb_decimator_ccf::sptr + typedef boost::shared_ptr<pfb_decimator_ccf> sptr; + + /*! + * Build the polyphase filterbank decimator. + * \param decim (unsigned integer) Specifies the decimation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param channel (unsigned integer) Selects the channel to return [default=0]. + */ + static sptr make(unsigned int decim, + const std::vector<float> &taps, + unsigned int channel); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + + //virtual void set_channel(unsigned int channel) = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_DECIMATOR_CCF_H */ diff --git a/gr-filter/include/filter/pfb_interpolator_ccf.h b/gr-filter/include/filter/pfb_interpolator_ccf.h new file mode 100644 index 0000000000..df28ab64d6 --- /dev/null +++ b/gr-filter/include/filter/pfb_interpolator_ccf.h @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_INTERPOLATOR_CCF_H +#define INCLUDED_PFB_INTERPOLATOR_CCF_H + +#include <filter/api.h> +#include <gr_sync_interpolator.h> + +namespace gr { + namespace filter { + + /*! + * \class gr_pfb_interpolator_ccf + * + * \brief Polyphase filterbank interpolator with gr_complex input, + * gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs interger up- + * sampling (interpolation) with a polyphase filterbank. The first + * input is the integer specifying how much to interpolate by. The + * second input is a vector (Python list) of floating-point taps + * of the prototype filter. + * + * The filter's taps should be based on the interpolation rate + * specified. That is, the bandwidth specified is relative to the + * bandwidth after interpolation. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, ATT, and the filter window function (a + * Blackman-harris window in this case). The first input is the + * gain, which is also specified as the interpolation rate so that + * the output levels are the same as the input (this creates an + * overall increase in power). + * + * <B><EM>self._taps = filter.firdes.low_pass_2(interp, interp*fs, BW, TB, + * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The PFB interpolator code takes the taps generated above and + * builds a set of filters. The set contains <EM>interp</EM> + * number of filters and each filter contains + * ceil(taps.size()/interp) number of taps. Each tap from the + * filter prototype is sequentially inserted into the next + * filter. When all of the input taps are used, the remaining + * filters in the filterbank are filled out with 0's to make sure + * each filter has the same number of taps. + * + * The theory behind this block can be found in Chapter 7.1 of the + * following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems</EM>," Upper Saddle River, NJ: Prentice Hall, + * Inc. 2004.</EM></B> + */ + + class FILTER_API pfb_interpolator_ccf : virtual public gr_sync_interpolator + { + public: + // gr::filter::pfb_interpolator_ccf::sptr + typedef boost::shared_ptr<pfb_interpolator_ccf> sptr; + + /*! + * Build the polyphase filterbank interpolator. + * \param interp (unsigned integer) Specifies the interpolation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the interpolated sampling rate. + */ + static sptr make(unsigned int interp, + const std::vector<float> &taps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_PFB_INTERPOLATOR_CCF_H */ diff --git a/gr-filter/include/filter/pfb_synthesizer_ccf.h b/gr-filter/include/filter/pfb_synthesizer_ccf.h new file mode 100644 index 0000000000..faa16990cc --- /dev/null +++ b/gr-filter/include/filter/pfb_synthesizer_ccf.h @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_SYNTHESIZER_CCF_H +#define INCLUDED_PFB_SYNTHESIZER_CCF_H + +#include <filter/api.h> +#include <gr_sync_interpolator.h> + +namespace gr { + namespace filter { + + /*! + * \class pfb_synthesizer_ccf + * + * \brief Polyphase synthesis filterbank with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + */ + + class FILTER_API pfb_synthesizer_ccf : virtual public gr_sync_interpolator + { + public: + // gr::filter::pfb_synthesizer_ccf::sptr + typedef boost::shared_ptr<pfb_synthesizer_ccf> sptr; + + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of + * channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter to + * populate the filterbank. + * \param twox (bool) use 2x oversampling or not (default is no) + */ + static sptr make(unsigned int numchans, + const std::vector<float> &taps, + bool twox=false); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to + * populate the filterbank. + */ + virtual void set_taps(const std::vector<float> &taps) = 0; + + /*! + * Print all of the filterbank taps to screen. + */ + virtual void print_taps() = 0; + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + virtual std::vector<std::vector<float> > taps() const = 0; + + /*! + * Set the channel map. Channels are numbers as: + * N/2+1 | ... | N-1 | 0 | 1 | 2 | ... | N/2 + * <------------------- 0 --------------------> + * freq + * + * So input stream 0 goes to channel 0, etc. Setting a new channel + * map allows the user to specify where in frequency he/she wants + * the input stream to go. This is especially useful to avoid + * putting signals into the channels on the edge of the spectrum + * which can either wrap around (in the case of odd number of + * channels) and be affected by filter rolloff in the transmitter. + * + * The map must be at least the number of streams being sent to the + * block. Less and the algorithm will not have enough data to + * properly setup the buffers. Any more channels specified will be + * ignored. + */ + virtual void set_channel_map(const std::vector<int> &map) = 0; + + /*! + * Gets the current channel map. + */ + virtual std::vector<int> channel_map() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_SYNTHESIZER_CCF_H */ diff --git a/gr-filter/include/filter/pm_remez.h b/gr-filter/include/filter/pm_remez.h new file mode 100644 index 0000000000..a57e9e276d --- /dev/null +++ b/gr-filter/include/filter/pm_remez.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_PM_REMEZ_H +#define INCLUDED_FILTER_PM_REMEZ_H + +#include <filter/api.h> +#include <gr_types.h> +#include <string> +#include <stdexcept> + +namespace gr { + namespace filter { + /*! + * \brief Parks-McClellan FIR filter design using Remez algorithm. + * + * \ingroup filter_design + * + * Calculates the optimal (in the Chebyshev/minimax sense) FIR + * filter inpulse reponse given a set of band edges, the desired + * reponse on those bands, and the weight given to the error in + * those bands. + * + * \param order filter order (number of taps in the returned filter - 1) + * \param bands frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...] + * \param ampl desired amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...] + * \param error_weight weighting applied to each band (usually 1) + * \param filter_type one of "bandpass", "hilbert" or "differentiator" + * \param grid_density determines how accurately the filter will be constructed. \ + * The minimum value is 16; higher values are slower to compute. + * + * Frequency is in the range [0, 1], with 1 being the Nyquist + * frequency (Fs/2) + * + * \returns vector of computed taps + * + * \throws std::runtime_error if args are invalid or calculation + * fails to converge. + */ + + FILTER_API std::vector<double> + pm_remez(int order, + const std::vector<double> &bands, + const std::vector<double> &l, + const std::vector<double> &error_weight, + const std::string filter_type = "bandpass", + int grid_density = 16 + ) throw (std::runtime_error); + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_PM_REMEZ_H */ diff --git a/gr-filter/include/filter/polyphase_filterbank.h b/gr-filter/include/filter/polyphase_filterbank.h new file mode 100644 index 0000000000..33e9522e17 --- /dev/null +++ b/gr-filter/include/filter/polyphase_filterbank.h @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_FILTER_POLYPHASE_FILTERBANK_H +#define INCLUDED_FILTER_POLYPHASE_FILTERBANK_H + +#include <filter/api.h> +#include <filter/fir_filter.h> +#include <fft/fft.h> + +namespace gr { + namespace filter { + namespace kernel { + + /*! + * \class polyphase_filterbank + * + * \brief Polyphase filterbank parent class + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in complex inputs and channelizes it to + * <EM>M</EM> channels of equal bandwidth. Each of the resulting + * channels is decimated to the new rate that is the input + * sampling rate <EM>fs</EM> divided by the number of channels, + * <EM>M</EM>. + * + * The PFB channelizer code takes the taps generated above and + * builds a set of filters. The set contains <EM>M</EM> number + * of filters and each filter contains ceil(taps.size()/decim) + * number of taps. Each tap from the filter prototype is + * sequentially inserted into the next filter. When all of the + * input taps are used, the remaining filters in the filterbank + * are filled out with 0's to make sure each filter has the same + * number of taps. + * + * Each filter operates using the gr_fir filter classs of GNU + * Radio, which takes the input stream at <EM>i</EM> and + * performs the inner product calculation to <EM>i+(n-1)</EM> + * where <EM>n</EM> is the number of filter taps. To efficiently + * handle this in the GNU Radio structure, each filter input + * must come from its own input stream. So the channelizer must + * be provided with <EM>M</EM> streams where the input stream + * has been deinterleaved. This is most easily done using the + * gr_stream_to_streams block. + * + * The output is then produced as a vector, where index + * <EM>i</EM> in the vector is the next sample from the + * <EM>i</EM>th channel. This is most easily handled by sending + * the output to a gr_vector_to_streams block to handle the + * conversion and passing <EM>M</EM> streams out. + * + * The input and output formatting is done using a hier_block2 + * called pfb_channelizer_ccf. This can take in a single stream + * and outputs <EM>M</EM> streams based on the behavior + * described above. + * + * The filter's taps should be based on the input sampling rate. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, <EM>ATT</EM>, and the filter window + * function (a Blackman-harris window in this case). The first + * input is the gain of the filter, which we specify here as + * unity. + * + * <B><EM>self._taps = filter.firdes.low_pass_2(1, fs, BW, TB, + * attenuation_dB=ATT, window=filter.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * More on the theory of polyphase filterbanks can be found in + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for + * Communication Systems," Upper Saddle River, NJ: + * Prentice Hall, Inc. 2004.</EM></B> + * + */ + + class FILTER_API polyphase_filterbank + { + protected: + unsigned int d_nfilts; + std::vector<kernel::fir_filter_ccf*> d_filters; + std::vector< std::vector<float> > d_taps; + unsigned int d_taps_per_filter; + fft::fft_complex *d_fft; + + public: + /*! + * Build the polyphase filterbank decimator. + * \param nfilts (unsigned integer) Specifies the number of + * channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter to + * populate the filterbank. + */ + polyphase_filterbank(unsigned int nfilts, + const std::vector<float> &taps); + + ~polyphase_filterbank(); + + /*! + * Update the filterbank's filter taps from a prototype + * filter. + * + * \param taps (vector/list of floats) The prototype filter to + * populate the filterbank. + */ + void set_taps(const std::vector<float> &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + std::vector<std::vector<float> > taps() const; + }; + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_POLYPHASE_FILTERBANK_H */ diff --git a/gr-filter/include/filter/rational_resampler_base_XXX.h.t b/gr-filter/include/filter/rational_resampler_base_XXX.h.t new file mode 100644 index 0000000000..e47a16ec6d --- /dev/null +++ b/gr-filter/include/filter/rational_resampler_base_XXX.h.t @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/api.h> +#include <gr_block.h> + + +namespace gr { + namespace filter { + + /*! + * \brief Rational Resampling Polyphase FIR filter with @I_TYPE@ + * input, @O_TYPE@ output and @TAP_TYPE@ taps. + * + *\ingroup filter_blk + */ + class FILTER_API @NAME@ : virtual public gr_block + { + public: + // gr::filter::@BASE_NAME@::sptr + typedef boost::shared_ptr<@BASE_NAME@> sptr; + + static sptr make(unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps); + + virtual unsigned interpolation() const = 0; + virtual unsigned decimation() const = 0; + + virtual void set_taps(const std::vector<@TAP_TYPE@> &taps) = 0; + virtual std::vector<@TAP_TYPE@> taps() const = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/include/filter/single_pole_iir.h b/gr-filter/include/filter/single_pole_iir.h new file mode 100644 index 0000000000..10d1b4791b --- /dev/null +++ b/gr-filter/include/filter/single_pole_iir.h @@ -0,0 +1,200 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SINGLE_POLE_IIR_H +#define INCLUDED_SINGLE_POLE_IIR_H + +#include <filter/api.h> +#include <stdexcept> +#include <gr_complex.h> + +namespace gr { + namespace filter { + + /*! + * \brief class template for single pole IIR filter + */ + template<class o_type, class i_type, class tap_type> + class single_pole_iir + { + public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) + */ + single_pole_iir(tap_type alpha = 1.0) + { + d_prev_output = 0; + set_taps(alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter(const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN(o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps(tap_type alpha) + { + if(alpha < 0 || alpha > 1) + throw std::out_of_range("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset() + { + d_prev_output = 0; + } + + o_type prev_output() const { return d_prev_output; } + + protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + o_type d_prev_output; + }; + + // + // general case. We may want to specialize this + // + template<class o_type, class i_type, class tap_type> + o_type + single_pole_iir<o_type, i_type, tap_type>::filter(const i_type input) + { + o_type output; + + output = d_alpha * input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (o_type) output; + } + + + template<class o_type, class i_type, class tap_type> + void + single_pole_iir<o_type, i_type, tap_type>::filterN(o_type output[], + const i_type input[], + unsigned long n) + { + for(unsigned i = 0; i < n; i++) + output[i] = filter(input[i]); + } + + + // + // Specialized case for gr_complex output and double taps + // We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double) + + template<class i_type> + class single_pole_iir<gr_complex, i_type, double> + { + public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) + */ + single_pole_iir(double alpha = 1.0) + { + d_prev_output = 0; + set_taps(alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + gr_complex filter(const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN(gr_complex output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps(double alpha) + { + if(alpha < 0 || alpha > 1) + throw std::out_of_range("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset() + { + d_prev_output = 0; + } + + gr_complexd prev_output() const { return d_prev_output; } + + protected: + double d_alpha; + double d_one_minus_alpha; + gr_complexd d_prev_output; + }; + + template< class i_type> + gr_complex + single_pole_iir<gr_complex, i_type, double>::filter(const i_type input) + { + gr_complexd output; + + output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (gr_complex) output; + } + + //Do we need to specialize this, although it is the same as the general case? + + template<class i_type> + void + single_pole_iir<gr_complex, i_type, double>::filterN(gr_complex output[], + const i_type input[], + unsigned long n) + { + for(unsigned i = 0; i < n; i++) + output[i] = filter(input[i]); + } + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_SINGLE_POLE_IIR_H */ diff --git a/gr-filter/include/filter/single_pole_iir_filter_cc.h b/gr-filter/include/filter/single_pole_iir_filter_cc.h new file mode 100644 index 0000000000..82febe8ec4 --- /dev/null +++ b/gr-filter/include/filter/single_pole_iir_filter_cc.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004-2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H +#define INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H + +#include <filter/api.h> +#include <filter/single_pole_iir.h> +#include <gr_sync_block.h> +#include <gr_complex.h> + +namespace gr { + namespace filter { + + /*! + * \brief single pole IIR filter with complex input, complex output + * \ingroup filter_blk + * + * The input and output satisfy a difference equation of the form + \htmlonly + \f{ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f} + \endhtmlonly + + \xmlonly + y[n] - (1-alpha) y[n-1] = alpha x[n] + \endxmlonly + + * with the corresponding rational system function + \htmlonly + \f{ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f} + \endhtmlonly + + \xmlonly + H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}} + \endxmlonly + + * Note that some texts define the system function with a + in the + * denominator. If you're using that convention, you'll need to + * negate the feedback tap. + */ + class FILTER_API single_pole_iir_filter_cc : virtual public gr_sync_block + { + public: + // gr::filter::single_pole_iir_filter_cc::sptr + typedef boost::shared_ptr<single_pole_iir_filter_cc> sptr; + + static sptr make(double alpha, unsigned int vlen=1); + + virtual void set_taps(double alpha) = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_CC_H */ diff --git a/gr-filter/include/filter/single_pole_iir_filter_ff.h b/gr-filter/include/filter/single_pole_iir_filter_ff.h new file mode 100644 index 0000000000..d85688db84 --- /dev/null +++ b/gr-filter/include/filter/single_pole_iir_filter_ff.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H +#define INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H + +#include <filter/api.h> +#include <filter/single_pole_iir.h> +#include <gr_sync_block.h> +#include <gr_complex.h> + +namespace gr { + namespace filter { + + /*! + * \brief single pole IIR filter with float input, float output + * \ingroup filter_blk + * + * The input and output satisfy a difference equation of the form + \htmlonly + \f{ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f} + \endhtmlonly + + \xmlonly + y[n] - (1-alpha) y[n-1] = alpha x[n] + \endxmlonly + + * with the corresponding rational system function + \htmlonly + \f{ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f} + \endhtmlonly + + \xmlonly + H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}} + \endxmlonly + + * Note that some texts define the system function with a + in the + * denominator. If you're using that convention, you'll need to + * negate the feedback tap. + */ + class FILTER_API single_pole_iir_filter_ff : virtual public gr_sync_block + { + public: + // gr::filter::single_pole_iir_filter_ff::sptr + typedef boost::shared_ptr<single_pole_iir_filter_ff> sptr; + + static sptr make(double alpha, unsigned int vlen=1); + + virtual void set_taps (double alpha) = 0; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_FF_H */ diff --git a/gr-filter/lib/CMakeLists.txt b/gr-filter/lib/CMakeLists.txt new file mode 100644 index 0000000000..73d7d7bae1 --- /dev/null +++ b/gr-filter/lib/CMakeLists.txt @@ -0,0 +1,178 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# generate helper scripts to expand templated files +######################################################################## +include(GrPython) + +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py " +#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_CORE_PYTHONPATH}') +os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' +os.chdir('${CMAKE_CURRENT_BINARY_DIR}') + +if __name__ == '__main__': + import build_utils + root, inp = sys.argv[1:3] + for sig in sys.argv[3:]: + name = re.sub ('X+', sig, root) + d = build_utils.standard_impl_dict2(name, sig, 'filter') + build_utils.expand_template(d, inp) +") + +macro(expand_cc root) + #make a list of all the generated files + unset(expanded_files_cc) + unset(expanded_files_h) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc) + list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/${name}.h) + endforeach(sig) + + #create a command to generate the source files + add_custom_command( + OUTPUT ${expanded_files_cc} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.cc.t ${ARGN} + ) + + #create a command to generate the header file + add_custom_command( + OUTPUT ${expanded_files_h} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.h.t ${ARGN} + ) + + #make source files depends on headers to force generation + set_source_files_properties(${expanded_files_cc} + PROPERTIES OBJECT_DEPENDS "${expanded_files_h}" + ) + + #install rules for the generated cc files + list(APPEND generated_sources ${expanded_files_cc}) + list(APPEND generated_headers ${expanded_files_h}) +endmacro(expand_cc) + +######################################################################## +# Invoke macro to generate various sources +######################################################################## +expand_cc(fir_filter_XXX_impl ccc ccf fcc fff fsf scc) +expand_cc(freq_xlating_fir_filter_XXX_impl ccc ccf fcc fcf scf scc) +expand_cc(interp_fir_filter_XXX_impl ccc ccf fcc fff fsf scc) +expand_cc(rational_resampler_base_XXX_impl ccc ccf fcc fff fsf scc) + + +######################################################################## +# Setup the include and linker paths +######################################################################## +include_directories( + ${GR_FILTER_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${VOLK_INCLUDE_DIRS} + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_FFT_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} + ${CPPUNIT_INCLUDE_DIRS} +) + +link_directories(${FFT_LIBRARY_DIRS}) +link_directories(${Boost_LIBRARY_DIRS}) +link_directories(${FFTW3F_LIBRARY_DIRS}) + +######################################################################## +# Setup library +######################################################################## +list(APPEND filter_sources + fir_filter.cc + fir_filter_with_buffer.cc + fft_filter.cc + firdes.cc + mmse_fir_interpolator_cc.cc + mmse_fir_interpolator_ff.cc + pm_remez.cc + polyphase_filterbank.cc + ${generated_sources} + adaptive_fir_ccc_impl.cc + adaptive_fir_ccf_impl.cc + dc_blocker_cc_impl.cc + dc_blocker_ff_impl.cc + filter_delay_fc_impl.cc + fft_filter_ccc_impl.cc + fft_filter_fff_impl.cc + fractional_interpolator_cc_impl.cc + fractional_interpolator_ff_impl.cc + hilbert_fc_impl.cc + iir_filter_ffd_impl.cc + pfb_arb_resampler_ccf_impl.cc + pfb_arb_resampler_fff_impl.cc + pfb_channelizer_ccf_impl.cc + pfb_decimator_ccf_impl.cc + pfb_interpolator_ccf_impl.cc + pfb_synthesizer_ccf_impl.cc + single_pole_iir_filter_cc_impl.cc + single_pole_iir_filter_ff_impl.cc + channel_model_impl.cc +) + +list(APPEND filter_libs + gnuradio-core + gnuradio-fft + volk + ${Boost_LIBRARIES} + ${FFTW3F_LIBRARIES} +) + +add_library(gnuradio-filter SHARED ${filter_sources}) +target_link_libraries(gnuradio-filter ${filter_libs}) +GR_LIBRARY_FOO(gnuradio-filter RUNTIME_COMPONENT "filter_runtime" DEVEL_COMPONENT "filter_devel") +add_dependencies(gnuradio-filter gnuradio-fft filter_generated_includes filter_generated_swigs) + + +######################################################################## +# QA C++ Code for gr-filter +######################################################################## +list(APPEND test_gr_filter_sources + ${CMAKE_CURRENT_SOURCE_DIR}/test_gr_filter.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_filter.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_firdes.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_fir_filter_with_buffer.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_mmse_fir_interpolator_cc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_mmse_fir_interpolator_ff.cc +) + +add_executable(test-gr-filter ${test_gr_filter_sources}) +target_link_libraries( + test-gr-filter + gnuradio-core + gnuradio-filter + ${CPPUNIT_LIBRARIES} + ${Boost_LIBRARIES} +) + +GR_ADD_TEST(test_gr_filter test-gr-filter) diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.cc b/gr-filter/lib/adaptive_fir_ccc_impl.cc new file mode 100644 index 0000000000..515ef90cd0 --- /dev/null +++ b/gr-filter/lib/adaptive_fir_ccc_impl.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "adaptive_fir_ccc_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + adaptive_fir_ccc::sptr adaptive_fir_ccc::make(const char *name, int decimation, + const std::vector<gr_complex> &taps) + { + return gnuradio::get_initial_sptr(new adaptive_fir_ccc_impl + (name, decimation, taps)); + } + + adaptive_fir_ccc_impl::adaptive_fir_ccc_impl(const char *name, int decimation, + const std::vector<gr_complex> &taps) + : gr_sync_decimator(name, + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex)), + decimation), + kernel::fir_filter_ccc(decimation, taps), + d_updated(false) + { + set_history(d_ntaps); + } + + void + adaptive_fir_ccc_impl::set_taps(const std::vector<gr_complex> &taps) + { + d_new_taps = taps; + d_updated = true; + } + + std::vector<gr_complex> + adaptive_fir_ccc_impl::taps() const + { + return kernel::fir_filter_ccc::taps(); + } + + gr_complex + adaptive_fir_ccc_impl::error(const gr_complex &out) + { + return 0; + } + + void + adaptive_fir_ccc_impl::update_tap(gr_complex &tap, const gr_complex &in) + { + tap = tap; + } + + int + adaptive_fir_ccc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gr_complex *in = (gr_complex *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + if (d_updated) { + kernel::fir_filter_ccc::set_taps(d_new_taps); + set_history(d_ntaps); + d_updated = false; + return 0; // history requirements may have changed. + } + + // Call base class filtering function that uses + // overloaded error and update_tap functions. + if (decimation() == 1) { + filterN(out, in, noutput_items); + } + else { + filterNdec(out, in, noutput_items, + decimation()); + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/adaptive_fir_ccc_impl.h b/gr-filter/lib/adaptive_fir_ccc_impl.h new file mode 100644 index 0000000000..fd6274a1d6 --- /dev/null +++ b/gr-filter/lib/adaptive_fir_ccc_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H +#define INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H + +#include <filter/adaptive_fir_ccc.h> +#include <filter/fir_filter.h> +#include <gr_types.h> + +namespace gr { + namespace filter { + + class FILTER_API adaptive_fir_ccc_impl : public adaptive_fir_ccc, public kernel::fir_filter_ccc + { + private: + std::vector<gr_complex> d_new_taps; + bool d_updated; + + protected: + // Override to calculate error signal per output + gr_complex error(const gr_complex &out); + + // Override to calculate new weight from old, corresponding input + void update_tap(gr_complex &tap, const gr_complex &in); + + public: + void set_taps(const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps() const; + + adaptive_fir_ccc_impl(const char *name, int decimation, + const std::vector<gr_complex> &taps); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCC_IMPL_H */ diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.cc b/gr-filter/lib/adaptive_fir_ccf_impl.cc new file mode 100644 index 0000000000..004a9286bb --- /dev/null +++ b/gr-filter/lib/adaptive_fir_ccf_impl.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "adaptive_fir_ccf_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + adaptive_fir_ccf::sptr adaptive_fir_ccf::make(const char *name, int decimation, + const std::vector<float> &taps) + { + return gnuradio::get_initial_sptr(new adaptive_fir_ccf_impl + (name, decimation, taps)); + } + + adaptive_fir_ccf_impl::adaptive_fir_ccf_impl(const char *name, int decimation, + const std::vector<float> &taps) + : gr_sync_decimator(name, + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex)), + decimation), + kernel::fir_filter_ccf(decimation, taps), + d_updated(false) + { + set_history(d_ntaps); + } + + void + adaptive_fir_ccf_impl::set_taps(const std::vector<float> &taps) + { + d_new_taps = taps; + d_updated = true; + } + + std::vector<float> + adaptive_fir_ccf_impl::taps() + { + return kernel::fir_filter_ccf::taps(); + } + + float + adaptive_fir_ccf_impl::error(const gr_complex &out) + { + return 0; + } + + void + adaptive_fir_ccf_impl::update_tap(float &tap, const gr_complex &in) + { + tap = tap; + } + + int + adaptive_fir_ccf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gr_complex *in = (gr_complex *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + if (d_updated) { + kernel::fir_filter_ccf::set_taps(d_new_taps); + set_history(d_ntaps); + d_updated = false; + return 0; // history requirements may have changed. + } + + // Call base class filtering function that uses + // overloaded error and update_tap functions. + if (decimation() == 1) { + filterN(out, in, noutput_items); + } + else { + filterNdec(out, in, noutput_items, + decimation()); + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/adaptive_fir_ccf_impl.h b/gr-filter/lib/adaptive_fir_ccf_impl.h new file mode 100644 index 0000000000..a0c9581ea2 --- /dev/null +++ b/gr-filter/lib/adaptive_fir_ccf_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H +#define INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H + +#include <filter/adaptive_fir_ccf.h> +#include <filter/fir_filter.h> +#include <gr_types.h> + +namespace gr { + namespace filter { + + class FILTER_API adaptive_fir_ccf_impl : public adaptive_fir_ccf, public kernel::fir_filter_ccf + { + private: + std::vector<float> d_new_taps; + bool d_updated; + + protected: + // Override to calculate error signal per output + float error(const gr_complex &out); + + // Override to calculate new weight from old, corresponding input + void update_tap(float &tap, const gr_complex &in); + + public: + void set_taps(const std::vector<float> &taps); + std::vector<float> taps(); + + adaptive_fir_ccf_impl(const char *name, int decimation, + const std::vector<float> &taps); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_ADAPTIVE_FIR_CCF_IMPL_H */ diff --git a/gr-filter/lib/channel_model_impl.cc b/gr-filter/lib/channel_model_impl.cc new file mode 100644 index 0000000000..f9e9954794 --- /dev/null +++ b/gr-filter/lib/channel_model_impl.cc @@ -0,0 +1,135 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "channel_model_impl.h" +#include <gr_io_signature.h> +#include <iostream> + +namespace gr { + namespace filter { + + channel_model::sptr + channel_model::make(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed) + { + return gnuradio::get_initial_sptr + (new channel_model_impl(noise_voltage, + frequency_offset, + epsilon, + taps, + noise_seed)); + } + + // Hierarchical block constructor + channel_model_impl::channel_model_impl(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed) + : gr_hier_block2("gr_channel_model", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))) + { + d_taps = taps; + while(d_taps.size() < 2) { + d_taps.push_back(0); + } + + d_timing_offset = fractional_interpolator_cc::make(0, epsilon); + + d_multipath = fir_filter_ccc::make(1, d_taps); + + d_noise_adder = gr_make_add_cc(); + d_noise = gr_make_noise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed); + d_freq_offset = gr_make_sig_source_c(1, GR_SIN_WAVE, frequency_offset, 1.0, 0.0); + d_mixer_offset = gr_make_multiply_cc(); + + connect(self(), 0, d_timing_offset, 0); + connect(d_timing_offset, 0, d_multipath, 0); + connect(d_multipath, 0, d_mixer_offset, 0); + connect(d_freq_offset, 0, d_mixer_offset, 1); + connect(d_mixer_offset, 0, d_noise_adder, 1); + connect(d_noise, 0, d_noise_adder, 0); + connect(d_noise_adder, 0, self(), 0); + } + + channel_model_impl::~channel_model_impl() + { + } + + void + channel_model_impl::set_noise_voltage(double noise_voltage) + { + d_noise->set_amplitude(noise_voltage); + } + + void + channel_model_impl::set_frequency_offset(double frequency_offset) + { + d_freq_offset->set_frequency(frequency_offset); + } + + void + channel_model_impl::set_taps(const std::vector<gr_complex> &taps) + { + d_taps = taps; + while(d_taps.size() < 2) { + d_taps.push_back(0); + } + d_multipath->set_taps(d_taps); + } + + void + channel_model_impl::set_timing_offset(double epsilon) + { + d_timing_offset->set_interp_ratio(epsilon); + } + + double + channel_model_impl::noise_voltage() const + { + return d_noise->amplitude(); + } + + double + channel_model_impl::frequency_offset() const + { + return d_freq_offset->frequency(); + } + + std::vector<gr_complex> + channel_model_impl::taps() const + { + return d_multipath->taps(); + } + + double + channel_model_impl::timing_offset() const + { + return d_timing_offset->interp_ratio(); + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/channel_model_impl.h b/gr-filter/lib/channel_model_impl.h new file mode 100644 index 0000000000..95a63d7904 --- /dev/null +++ b/gr-filter/lib/channel_model_impl.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_CHANNEL_MODEL_IMPL_H +#define INCLUDED_FILTER_CHANNEL_MODEL_IMPL_H + +#include <gr_top_block.h> +#include <gr_sig_source_c.h> +#include <gr_add_cc.h> +#include <gr_multiply_cc.h> +#include <gr_noise_source_c.h> +#include <filter/channel_model.h> +#include <filter/fractional_interpolator_cc.h> +#include <filter/fir_filter_ccc.h> + +namespace gr { + namespace filter { + + class FILTER_API channel_model_impl : public channel_model + { + private: + gr_sig_source_c_sptr d_freq_offset; + gr_add_cc_sptr d_noise_adder; + gr_noise_source_c_sptr d_noise; + gr_multiply_cc_sptr d_mixer_offset; + + fractional_interpolator_cc::sptr d_timing_offset; + fir_filter_ccc::sptr d_multipath; + + std::vector<gr_complex> d_taps; + + public: + channel_model_impl(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed); + + ~channel_model_impl(); + + void set_noise_voltage(double noise_voltage); + void set_frequency_offset(double frequency_offset); + void set_taps(const std::vector<gr_complex> &taps); + void set_timing_offset(double epsilon); + + double noise_voltage() const; + double frequency_offset() const; + std::vector<gr_complex> taps() const; + double timing_offset() const; + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_CHANNEL_MODEL_IMPL_H */ diff --git a/gr-filter/lib/dc_blocker_cc_impl.cc b/gr-filter/lib/dc_blocker_cc_impl.cc new file mode 100644 index 0000000000..663ba94f1e --- /dev/null +++ b/gr-filter/lib/dc_blocker_cc_impl.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dc_blocker_cc_impl.h" +#include <gr_io_signature.h> +#include <cstdio> + +namespace gr { + namespace filter { + + moving_averager_c::moving_averager_c(int D) + : d_length(D), d_out(0), d_out_d1(0), d_out_d2(0) + { + d_delay_line = std::deque<gr_complex>(d_length-1, gr_complex(0,0)); + } + + moving_averager_c::~moving_averager_c() + { + } + + gr_complex + moving_averager_c::filter(gr_complex x) + { + d_out_d1 = d_out; + d_delay_line.push_back(x); + d_out = d_delay_line[0]; + d_delay_line.pop_front(); + + gr_complex y = x - d_out_d1 + d_out_d2; + d_out_d2 = y; + + return (y / (float)(d_length)); + } + + + + dc_blocker_cc::sptr dc_blocker_cc::make(int D, bool long_form) + { + return gnuradio::get_initial_sptr(new dc_blocker_cc_impl(D, long_form)); + } + + + dc_blocker_cc_impl::dc_blocker_cc_impl(int D, bool long_form) + : gr_sync_block("dc_blocker_cc", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex))), + d_length(D), d_long_form(long_form) + { + if(d_long_form) { + d_ma_0 = new moving_averager_c(D); + d_ma_1 = new moving_averager_c(D); + d_ma_2 = new moving_averager_c(D); + d_ma_3 = new moving_averager_c(D); + d_delay_line = std::deque<gr_complex>(d_length-1, gr_complex(0,0)); + } + else { + d_ma_0 = new moving_averager_c(D); + d_ma_1 = new moving_averager_c(D); + } + } + + dc_blocker_cc_impl::~dc_blocker_cc_impl() + { + if(d_long_form) { + delete d_ma_0; + delete d_ma_1; + delete d_ma_2; + delete d_ma_3; + } + else { + delete d_ma_0; + delete d_ma_1; + } + } + + int + dc_blocker_cc_impl::group_delay() + { + if(d_long_form) + return (2*d_length-2); + else + return d_length - 1; + } + + int + dc_blocker_cc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex*)input_items[0]; + gr_complex *out = (gr_complex*)output_items[0]; + + if(d_long_form) { + gr_complex y1, y2, y3, y4, d; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + y3 = d_ma_2->filter(y2); + y4 = d_ma_3->filter(y3); + + d_delay_line.push_back(d_ma_0->delayed_sig()); + d = d_delay_line[0]; + d_delay_line.pop_front(); + + out[i] = d - y4; + } + } + else { + gr_complex y1, y2; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + out[i] = d_ma_0->delayed_sig() - y2; + } + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/dc_blocker_cc_impl.h b/gr-filter/lib/dc_blocker_cc_impl.h new file mode 100644 index 0000000000..6f8bc16c76 --- /dev/null +++ b/gr-filter/lib/dc_blocker_cc_impl.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_FILTER_DC_BLOCKER_CC_IMPL_H +#define INCLUDED_FILTER_DC_BLOCKER_CC_IMPL_H + +#include <filter/dc_blocker_cc.h> +#include <deque> + +namespace gr { + namespace filter { + + class moving_averager_c + { + public: + moving_averager_c(int D); + ~moving_averager_c(); + + gr_complex filter(gr_complex x); + gr_complex delayed_sig() { return d_out; } + + private: + int d_length; + gr_complex d_out, d_out_d1, d_out_d2; + std::deque<gr_complex> d_delay_line; + }; + + class FILTER_API dc_blocker_cc_impl : public dc_blocker_cc + { + private: + int d_length; + bool d_long_form; + moving_averager_c *d_ma_0; + moving_averager_c *d_ma_1; + moving_averager_c *d_ma_2; + moving_averager_c *d_ma_3; + std::deque<gr_complex> d_delay_line; + + public: + dc_blocker_cc_impl(int D, bool long_form); + + ~dc_blocker_cc_impl(); + + int group_delay(); + + //int set_length(int D); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_DC_BLOCKER_CC_IMPL_H */ diff --git a/gr-filter/lib/dc_blocker_ff_impl.cc b/gr-filter/lib/dc_blocker_ff_impl.cc new file mode 100644 index 0000000000..22822d1476 --- /dev/null +++ b/gr-filter/lib/dc_blocker_ff_impl.cc @@ -0,0 +1,142 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "dc_blocker_ff_impl.h" +#include <gr_io_signature.h> +#include <cstdio> + +namespace gr { + namespace filter { + + moving_averager_f::moving_averager_f(int D) + : d_length(D), d_out(0), d_out_d1(0), d_out_d2(0) + { + d_delay_line = std::deque<float>(d_length-1, 0); + } + + moving_averager_f::~moving_averager_f() + { + } + + float + moving_averager_f::filter(float x) + { + d_out_d1 = d_out; + d_delay_line.push_back(x); + d_out = d_delay_line[0]; + d_delay_line.pop_front(); + + float y = x - d_out_d1 + d_out_d2; + d_out_d2 = y; + + return (y / (float)(d_length)); + } + + + dc_blocker_ff::sptr dc_blocker_ff::make(int D, bool long_form) + { + return gnuradio::get_initial_sptr(new dc_blocker_ff_impl(D, long_form)); + } + + dc_blocker_ff_impl::dc_blocker_ff_impl(int D, bool long_form) + : gr_sync_block("dc_blocker_ff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(float))), + d_length(D), d_long_form(long_form) + { + if(d_long_form) { + d_ma_0 = new moving_averager_f(D); + d_ma_1 = new moving_averager_f(D); + d_ma_2 = new moving_averager_f(D); + d_ma_3 = new moving_averager_f(D); + d_delay_line = std::deque<float>(d_length-1, 0); + } + else { + d_ma_0 = new moving_averager_f(D); + d_ma_1 = new moving_averager_f(D); + } + } + + dc_blocker_ff_impl::~dc_blocker_ff_impl() + { + if(d_long_form) { + delete d_ma_0; + delete d_ma_1; + delete d_ma_2; + delete d_ma_3; + } + else { + delete d_ma_0; + delete d_ma_1; + } + } + + int + dc_blocker_ff_impl::group_delay() + { + if(d_long_form) + return (2*d_length-2); + else + return d_length - 1; + } + + int + dc_blocker_ff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float*)input_items[0]; + float *out = (float*)output_items[0]; + + if(d_long_form) { + float y1, y2, y3, y4, d; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + y3 = d_ma_2->filter(y2); + y4 = d_ma_3->filter(y3); + + d_delay_line.push_back(d_ma_0->delayed_sig()); + d = d_delay_line[0]; + d_delay_line.pop_front(); + + out[i] = d - y4; + } + } + else { + float y1, y2; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + out[i] = d_ma_0->delayed_sig() - y2; + } + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/dc_blocker_ff_impl.h b/gr-filter/lib/dc_blocker_ff_impl.h new file mode 100644 index 0000000000..5ae60e2e42 --- /dev/null +++ b/gr-filter/lib/dc_blocker_ff_impl.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_FILTER_DC_BLOCKER_FF_IMPL_H +#define INCLUDED_FILTER_DC_BLOCKER_FF_IMPL_H + +#include <filter/dc_blocker_ff.h> +#include <deque> + +namespace gr { + namespace filter { + + class moving_averager_f + { + public: + moving_averager_f(int D); + ~moving_averager_f(); + + float filter(float x); + float delayed_sig() { return d_out; } + + private: + int d_length; + float d_out, d_out_d1, d_out_d2; + std::deque<float> d_delay_line; + }; + + class FILTER_API dc_blocker_ff_impl : public dc_blocker_ff + { + private: + int d_length; + bool d_long_form; + moving_averager_f *d_ma_0; + moving_averager_f *d_ma_1; + moving_averager_f *d_ma_2; + moving_averager_f *d_ma_3; + std::deque<float> d_delay_line; + + public: + dc_blocker_ff_impl(int D, bool long_form); + + ~dc_blocker_ff_impl(); + + int group_delay(); + + //int set_length(int D); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_DC_BLOCKER_FF_IMPL_H */ diff --git a/gr-filter/lib/fft_filter.cc b/gr-filter/lib/fft_filter.cc new file mode 100644 index 0000000000..1b256a3dad --- /dev/null +++ b/gr-filter/lib/fft_filter.cc @@ -0,0 +1,316 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <filter/fft_filter.h> +#include <volk/volk.h> +#include <iostream> +#include <cstring> + +namespace gr { + namespace filter { + namespace kernel { + + #define VERBOSE 0 + + fft_filter_fff::fft_filter_fff(int decimation, + const std::vector<float> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), + d_invfft(0), d_nthreads(nthreads) + { + set_taps(taps); + } + + fft_filter_fff::~fft_filter_fff() + { + delete d_fwdfft; + delete d_invfft; + fft::free(d_xformed_taps); + } + + /* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ + int + fft_filter_fff::set_taps(const std::vector<float> &taps) + { + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for(i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + float *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize/2+1; i++) + d_xformed_taps[i] = out[i]; + + return d_nsamples; + } + + // determine and set d_ntaps, d_nsamples, d_fftsize + void + fft_filter_fff::compute_sizes(int ntaps) + { + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if(VERBOSE) { + std::cerr << "fft_filter_fff: ntaps = " << d_ntaps + << " fftsize = " << d_fftsize + << " nsamples = " << d_nsamples << std::endl; + } + + // compute new plans + if(d_fftsize != old_fftsize) { + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new fft::fft_real_fwd(d_fftsize); + d_invfft = new fft::fft_real_rev(d_fftsize); + d_xformed_taps = fft::malloc_complex(d_fftsize/2+1); + } + } + + void + fft_filter_fff::set_nthreads(int n) + { + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); + } + + int + fft_filter_fff::nthreads() const + { + return d_nthreads; + } + + int + fft_filter_fff::filter(int nitems, const float *input, float *output) + { + int dec_ctr = 0; + int j = 0; + int ninput_items = nitems * d_decimation; + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + gr_complex *a = d_fwdfft->get_outbuf(); + gr_complex *b = d_xformed_taps; + gr_complex *c = d_invfft->get_inbuf(); + + volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize/2+1); + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + j = dec_ctr; + while (j < d_nsamples) { + *output++ = d_invfft->get_outbuf()[j]; + j += d_decimation; + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(float)); + } + + return nitems; + } + + + /**************************************************************/ + + + fft_filter_ccc::fft_filter_ccc(int decimation, + const std::vector<gr_complex> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), + d_invfft(0), d_nthreads(nthreads) + { + set_taps(taps); + } + + fft_filter_ccc::~fft_filter_ccc() + { + delete d_fwdfft; + delete d_invfft; + fft::free(d_xformed_taps); + } + + /* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ + int + fft_filter_ccc::set_taps(const std::vector<gr_complex> &taps) + { + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for(i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + gr_complex *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for(i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for(; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for(i = 0; i < d_fftsize; i++) + d_xformed_taps[i] = out[i]; + + return d_nsamples; + } + + // determine and set d_ntaps, d_nsamples, d_fftsize + void + fft_filter_ccc::compute_sizes(int ntaps) + { + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if(VERBOSE) { + std::cerr << "fft_filter_ccc: ntaps = " << d_ntaps + << " fftsize = " << d_fftsize + << " nsamples = " << d_nsamples << std::endl; + } + + // compute new plans + if(d_fftsize != old_fftsize) { + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new fft::fft_complex(d_fftsize, true, d_nthreads); + d_invfft = new fft::fft_complex(d_fftsize, false, d_nthreads); + d_xformed_taps = fft::malloc_complex(d_fftsize); + } + } + + void + fft_filter_ccc::set_nthreads(int n) + { + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); + } + + int + fft_filter_ccc::nthreads() const + { + return d_nthreads; + } + + int + fft_filter_ccc::filter(int nitems, const gr_complex *input, gr_complex *output) + { + int dec_ctr = 0; + int j = 0; + int ninput_items = nitems * d_decimation; + + for(int i = 0; i < ninput_items; i += d_nsamples) { + memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex)); + + for(j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + gr_complex *a = d_fwdfft->get_outbuf(); + gr_complex *b = d_xformed_taps; + gr_complex *c = d_invfft->get_inbuf(); + + volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize); + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for(j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + j = dec_ctr; + while(j < d_nsamples) { + *output++ = d_invfft->get_outbuf()[j]; + j += d_decimation; + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(gr_complex)); + } + + return nitems; + } + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fft_filter_ccc_impl.cc b/gr-filter/lib/fft_filter_ccc_impl.cc new file mode 100644 index 0000000000..0a20029917 --- /dev/null +++ b/gr-filter/lib/fft_filter_ccc_impl.cc @@ -0,0 +1,118 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fft_filter_ccc_impl.h" +#include <gr_io_signature.h> + +#include <math.h> +#include <assert.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + fft_filter_ccc::sptr fft_filter_ccc::make(int decimation, + const std::vector<gr_complex> &taps, + int nthreads) + { + return gnuradio::get_initial_sptr(new fft_filter_ccc_impl + (decimation, taps, nthreads)); + } + + fft_filter_ccc_impl::fft_filter_ccc_impl(int decimation, + const std::vector<gr_complex> &taps, + int nthreads) + : gr_sync_decimator("fft_filter_ccc", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + decimation), + d_updated(false) + { + set_history(1); + + d_filter = new kernel::fft_filter_ccc(decimation, taps, nthreads); + + d_new_taps = taps; + d_nsamples = d_filter->set_taps(taps); + set_output_multiple(d_nsamples); + } + + fft_filter_ccc_impl::~fft_filter_ccc_impl() + { + delete d_filter; + } + + void + fft_filter_ccc_impl::set_taps(const std::vector<gr_complex> &taps) + { + d_new_taps = taps; + d_updated = true; + } + + std::vector<gr_complex> + fft_filter_ccc_impl::taps() const + { + return d_new_taps; + } + + void + fft_filter_ccc_impl::set_nthreads(int n) + { + if(d_filter) + d_filter->set_nthreads(n); + } + + int + fft_filter_ccc_impl::nthreads() const + { + if(d_filter) + return d_filter->nthreads(); + else + return 0; + } + + int + fft_filter_ccc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated){ + d_nsamples = d_filter->set_taps(d_new_taps); + d_updated = false; + set_output_multiple(d_nsamples); + return 0; // output multiple may have changed + } + + d_filter->filter(noutput_items, in, out); + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fft_filter_ccc_impl.h b/gr-filter/lib/fft_filter_ccc_impl.h new file mode 100644 index 0000000000..82be009153 --- /dev/null +++ b/gr-filter/lib/fft_filter_ccc_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H +#define INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H + +#include <filter/api.h> +#include <filter/fft_filter.h> +#include <filter/fft_filter_ccc.h> + +namespace gr { + namespace filter { + + class FILTER_API fft_filter_ccc_impl : public fft_filter_ccc + { + private: + int d_nsamples; + bool d_updated; + kernel::fft_filter_ccc *d_filter; + std::vector<gr_complex> d_new_taps; + + public: + fft_filter_ccc_impl(int decimation, + const std::vector<gr_complex> &taps, + int nthreads=1); + + ~fft_filter_ccc_impl(); + + void set_taps(const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps() const; + + void set_nthreads(int n); + int nthreads() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FFT_FILTER_CCC_IMPL_H */ diff --git a/gr-filter/lib/fft_filter_fff_impl.cc b/gr-filter/lib/fft_filter_fff_impl.cc new file mode 100644 index 0000000000..1d6eb02db1 --- /dev/null +++ b/gr-filter/lib/fft_filter_fff_impl.cc @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "fft_filter_fff_impl.h" +#include <gr_io_signature.h> + +#include <math.h> +#include <assert.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + fft_filter_fff::sptr fft_filter_fff::make(int decimation, + const std::vector<float> &taps, + int nthreads) + { + return gnuradio::get_initial_sptr(new fft_filter_fff_impl + (decimation, taps, nthreads)); + } + + + fft_filter_fff_impl::fft_filter_fff_impl(int decimation, + const std::vector<float> &taps, + int nthreads) + : gr_sync_decimator("fft_filter_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(float)), + decimation), + d_updated(false) + { + set_history(1); + + d_filter = new kernel::fft_filter_fff(decimation, taps, nthreads); + + d_new_taps = taps; + d_nsamples = d_filter->set_taps(taps); + set_output_multiple(d_nsamples); + } + + fft_filter_fff_impl::~fft_filter_fff_impl() + { + delete d_filter; + } + + void + fft_filter_fff_impl::set_taps(const std::vector<float> &taps) + { + d_new_taps = taps; + d_updated = true; + } + + std::vector<float> + fft_filter_fff_impl::taps() const + { + return d_new_taps; + } + + void + fft_filter_fff_impl::set_nthreads(int n) + { + if(d_filter) + d_filter->set_nthreads(n); + } + + int + fft_filter_fff_impl::nthreads() const + { + if(d_filter) + return d_filter->nthreads(); + else + return 0; + } + + int + fft_filter_fff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *)input_items[0]; + float *out = (float *)output_items[0]; + + if (d_updated){ + d_nsamples = d_filter->set_taps(d_new_taps); + d_updated = false; + set_output_multiple(d_nsamples); + return 0; // output multiple may have changed + } + + d_filter->filter(noutput_items, in, out); + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fft_filter_fff_impl.h b/gr-filter/lib/fft_filter_fff_impl.h new file mode 100644 index 0000000000..df35d3df7b --- /dev/null +++ b/gr-filter/lib/fft_filter_fff_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H +#define INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H + +#include <filter/api.h> +#include <filter/fft_filter.h> +#include <filter/fft_filter_fff.h> + +namespace gr { + namespace filter { + + class FILTER_API fft_filter_fff_impl : public fft_filter_fff + { + private: + int d_nsamples; + bool d_updated; + kernel::fft_filter_fff *d_filter; + std::vector<float> d_new_taps; + + public: + fft_filter_fff_impl(int decimation, + const std::vector<float> &taps, + int nthreads=1); + + ~fft_filter_fff_impl(); + + void set_taps(const std::vector<float> &taps); + std::vector<float> taps() const; + + void set_nthreads(int n); + int nthreads() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FFT_FILTER_FFF_IMPL_H */ diff --git a/gr-filter/lib/filter_delay_fc_impl.cc b/gr-filter/lib/filter_delay_fc_impl.cc new file mode 100644 index 0000000000..3bb5508642 --- /dev/null +++ b/gr-filter/lib/filter_delay_fc_impl.cc @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "filter_delay_fc_impl.h" +#include <volk/volk.h> + +namespace gr { + namespace filter { + + filter_delay_fc::sptr filter_delay_fc::make(const std::vector<float> &taps) + { + return gnuradio::get_initial_sptr(new filter_delay_fc_impl(taps)); + } + + filter_delay_fc_impl::filter_delay_fc_impl(const std::vector<float> &taps) + : gr_sync_block("filter_delay_fc", + gr_make_io_signature(1, 2, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(gr_complex))), + d_update(false) + { + d_taps = taps; + d_fir = new kernel::fir_filter_fff(1, taps); + d_delay = d_fir->ntaps() / 2; + set_history(d_fir->ntaps()); + + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1, alignment_multiple)); + } + + filter_delay_fc_impl::~filter_delay_fc_impl() + { + delete d_fir; + } + + std::vector<float> + filter_delay_fc_impl::taps() + { + return d_fir->taps(); + } + + void + filter_delay_fc_impl::set_taps(const std::vector<float> &taps) + { + // don't reset taps in case history changes + d_taps = taps; + d_update = true; + } + + int + filter_delay_fc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + float *in0 = (float *)input_items[0]; + float *in1 = (float *)input_items[1]; + gr_complex *out = (gr_complex *)output_items[0]; + + if(d_update) { + d_fir->set_taps(d_taps); + d_delay = d_fir->ntaps() / 2; + set_history(d_fir->ntaps()); + return 0; + } + + switch(input_items.size ()) { + case 1: + for(int i = 0; i < noutput_items; i++) { + out[i] = gr_complex(in0[i + d_delay], + d_fir->filter(&in0[i])); + } + break; + + case 2: + for(int j = 0; j < noutput_items; j++) { + out[j] = gr_complex(in0[j + d_delay], + d_fir->filter(&in1[j])); + } + break; + + default: + assert(0); + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/filter_delay_fc_impl.h b/gr-filter/lib/filter_delay_fc_impl.h new file mode 100644 index 0000000000..5157d6e022 --- /dev/null +++ b/gr-filter/lib/filter_delay_fc_impl.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_FILTER_DELAY_FC_IMPL_H +#define INCLUDED_FILTER_FILTER_DELAY_FC_IMPL_H + +#include <filter/filter_delay_fc.h> +#include <filter/fir_filter.h> +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + class FILTER_API filter_delay_fc_impl : public filter_delay_fc + { + private: + unsigned int d_delay; + kernel::fir_filter_fff *d_fir; + std::vector<float> d_taps; + bool d_update; + + public: + filter_delay_fc_impl(const std::vector<float> &taps); + ~filter_delay_fc_impl(); + + std::vector<float> taps(); + void set_taps(const std::vector<float> &taps); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_FILTER_DELAY_FC_IMPL_H */ diff --git a/gr-filter/lib/fir_filter.cc b/gr-filter/lib/fir_filter.cc new file mode 100644 index 0000000000..2334058241 --- /dev/null +++ b/gr-filter/lib/fir_filter.cc @@ -0,0 +1,667 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <filter/fir_filter.h> +#include <fft/fft.h> +#include <volk/volk.h> +#include <cstdio> +#include <cstring> + +namespace gr { + namespace filter { + namespace kernel { + + fir_filter_fff::fir_filter_fff(int decimation, + const std::vector<float> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(float); + + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_float(1); + } + + fir_filter_fff::~fir_filter_fff() + { + // Free all aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_fff::set_taps(const std::vector<float> &taps) + { + // Free the taps if already allocated + if(d_aligned_taps!= NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // Make a set of taps at all possible arch alignments + d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + } + + std::vector<float> + fir_filter_fff::taps() const + { + std::vector<float> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + unsigned int + fir_filter_fff::ntaps() const + { + return d_ntaps; + } + + float + fir_filter_fff::filter(const float input[]) + { + const float *ar = (float *)((unsigned long) input & ~(d_align-1)); + unsigned al = input - ar; + + volk_32f_x2_dot_prod_32f_a(d_output, ar, + d_aligned_taps[al], + d_ntaps+al); + return *d_output; + } + + void + fir_filter_fff::filterN(float output[], + const float input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[i]); + } + } + + void + fir_filter_fff::filterNdec(float output[], + const float input[], + unsigned long n, + unsigned int decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[j]); + j += decimate; + } + } + + /**************************************************************/ + + fir_filter_ccf::fir_filter_ccf(int decimation, + const std::vector<float> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(gr_complex); + + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_complex(1); + } + + fir_filter_ccf::~fir_filter_ccf() + { + // Free all aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_ccf::set_taps(const std::vector<float> &taps) + { + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // Make a set of taps at all possible arch alignments + d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + } + + std::vector<float> + fir_filter_ccf::taps() const + { + std::vector<float> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + unsigned int + fir_filter_ccf::ntaps() const + { + return d_ntaps; + } + + gr_complex + fir_filter_ccf::filter(const gr_complex input[]) + { + const gr_complex *ar = (gr_complex *)((unsigned long) input & ~(d_align-1)); + unsigned al = input - ar; + + volk_32fc_32f_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + (d_ntaps+al)); + return *d_output; + } + + void + fir_filter_ccf::filterN(gr_complex output[], + const gr_complex input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) + output[i] = filter(&input[i]); + } + + + void + fir_filter_ccf::filterNdec(gr_complex output[], + const gr_complex input[], + unsigned long n, + unsigned int decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++){ + output[i] = filter(&input[j]); + j += decimate; + } + } + + + /**************************************************************/ + + + fir_filter_fcc::fir_filter_fcc(int decimation, + const std::vector<gr_complex> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(float); + + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_complex(1); + } + + fir_filter_fcc::~fir_filter_fcc() + { + // Free all aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_fcc::set_taps(const std::vector<gr_complex> &taps) + { + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // Make a set of taps at all possible arch alignments + d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + } + + std::vector<gr_complex> + fir_filter_fcc::taps() const + { + std::vector<gr_complex> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + unsigned int + fir_filter_fcc::ntaps() const + { + return d_ntaps; + } + + gr_complex + fir_filter_fcc::filter(const float input[]) + { + const float *ar = (float *)((unsigned long) input & ~(d_align-1)); + unsigned al = input - ar; + + volk_32fc_32f_dot_prod_32fc_a(d_output, + d_aligned_taps[al], + ar, + (d_ntaps+al)); + return *d_output; + } + + void + fir_filter_fcc::filterN(gr_complex output[], + const float input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) + output[i] = filter(&input[i]); + } + + + void + fir_filter_fcc::filterNdec(gr_complex output[], + const float input[], + unsigned long n, + unsigned int decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++){ + output[i] = filter(&input[j]); + j += decimate; + } + } + + /**************************************************************/ + + fir_filter_ccc::fir_filter_ccc(int decimation, + const std::vector<gr_complex> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(gr_complex); + + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_complex(1); + } + + fir_filter_ccc::~fir_filter_ccc() + { + // Free all aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_ccc::set_taps(const std::vector<gr_complex> &taps) + { + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // Make a set of taps at all possible arch alignments + d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + } + + std::vector<gr_complex> + fir_filter_ccc::taps() const + { + std::vector<gr_complex> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + unsigned int + fir_filter_ccc::ntaps() const + { + return d_ntaps; + } + + gr_complex + fir_filter_ccc::filter(const gr_complex input[]) + { + const gr_complex *ar = (gr_complex *)((unsigned long) input & ~(d_align-1)); + unsigned al = input - ar; + + volk_32fc_x2_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + (d_ntaps+al)*sizeof(gr_complex)); + return *d_output; + } + + void + fir_filter_ccc::filterN(gr_complex output[], + const gr_complex input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) + output[i] = filter(&input[i]); + } + + + void + fir_filter_ccc::filterNdec(gr_complex output[], + const gr_complex input[], + unsigned long n, + unsigned int decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++){ + output[i] = filter(&input[j]); + j += decimate; + } + } + + /**************************************************************/ + + fir_filter_scc::fir_filter_scc(int decimation, + const std::vector<gr_complex> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(short); + + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_complex(1); + } + + fir_filter_scc::~fir_filter_scc() + { + // Free all aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_scc::set_taps(const std::vector<gr_complex> &taps) + { + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // Make a set of taps at all possible arch alignments + d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + } + + std::vector<gr_complex> + fir_filter_scc::taps() const + { + std::vector<gr_complex> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + unsigned int + fir_filter_scc::ntaps() const + { + return d_ntaps; + } + + gr_complex + fir_filter_scc::filter(const short input[]) + { + const short *ar = (short *)((unsigned long) input & ~(d_align-1)); + unsigned al = input - ar; + + volk_16i_32fc_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + (d_ntaps+al)); + + return *d_output; + } + + void + fir_filter_scc::filterN(gr_complex output[], + const short input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) + output[i] = filter(&input[i]); + } + + + void + fir_filter_scc::filterNdec(gr_complex output[], + const short input[], + unsigned long n, + unsigned int decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++){ + output[i] = filter(&input[j]); + j += decimate; + } + } + + /**************************************************************/ + + fir_filter_fsf::fir_filter_fsf(int decimation, + const std::vector<float> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(float); + + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = (short*)fft::malloc_float(1); + } + + fir_filter_fsf::~fir_filter_fsf() + { + // Free all aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_fsf::set_taps(const std::vector<float> &taps) + { + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // Make a set of taps at all possible arch alignments + d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + } + + std::vector<float> + fir_filter_fsf::taps() const + { + std::vector<float> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + unsigned int + fir_filter_fsf::ntaps() const + { + return d_ntaps; + } + + short + fir_filter_fsf::filter(const float input[]) + { + const float *ar = (float *)((unsigned long) input & ~(d_align-1)); + unsigned al = input - ar; + + volk_32f_x2_dot_prod_16i_a(d_output, ar, + d_aligned_taps[al], + (d_ntaps+al)); + + return *d_output; + } + + void + fir_filter_fsf::filterN(short output[], + const float input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) + output[i] = filter(&input[i]); + } + + void + fir_filter_fsf::filterNdec(short output[], + const float input[], + unsigned long n, + unsigned int decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++){ + output[i] = filter(&input[j]); + j += decimate; + } + } + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fir_filter_XXX_impl.cc.t b/gr-filter/lib/fir_filter_XXX_impl.cc.t new file mode 100644 index 0000000000..529c51e2bb --- /dev/null +++ b/gr-filter/lib/fir_filter_XXX_impl.cc.t @@ -0,0 +1,104 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "@IMPL_NAME@.h" +#include <gr_io_signature.h> +#include <volk/volk.h> + +namespace gr { + namespace filter { + + @BASE_NAME@::sptr + @BASE_NAME@::make(int decimation, const std::vector<@TAP_TYPE@> &taps) + { + return gnuradio::get_initial_sptr(new @IMPL_NAME@ + (decimation, taps)); + } + + + @IMPL_NAME@::@IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps) + : gr_sync_decimator("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@)), + decimation) + { + d_fir = new kernel::@BASE_NAME@(decimation, taps); + d_updated = false; + set_history(d_fir->ntaps()); + + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1, alignment_multiple)); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + delete d_fir; + } + + void + @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps) + { + d_fir->set_taps(taps); + d_updated = true; + } + + std::vector<@TAP_TYPE@> + @IMPL_NAME@::taps() const + { + return d_fir->taps(); + } + + int + @IMPL_NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@*)output_items[0]; + + if (d_updated) { + set_history(d_fir->ntaps()); + d_updated = false; + return 0; // history requirements may have changed. + } + + if (decimation() == 1) { + d_fir->filterN(out, in, noutput_items); + } + else { + d_fir->filterNdec(out, in, noutput_items, + decimation()); + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ + diff --git a/gnuradio-core/src/lib/general/gri_glfsr.h b/gr-filter/lib/fir_filter_XXX_impl.h.t index 9aae2d9f17..ef0a7adfee 100644 --- a/gnuradio-core/src/lib/general/gri_glfsr.h +++ b/gr-filter/lib/fir_filter_XXX_impl.h.t @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007 Free Software Foundation, Inc. + * Copyright 2004,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,38 +20,37 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GRI_GLFSR_H -#define INCLUDED_GRI_GLFSR_H +/* @WARNING@ */ -#include <gr_core_api.h> +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ -/*! - * \brief Galois Linear Feedback Shift Register using specified polynomial mask - * \ingroup misc - * - * Generates a maximal length pseudo-random sequence of length 2^degree-1 - */ +#include <filter/fir_filter.h> +#include <filter/@BASE_NAME@.h> + +namespace gr { + namespace filter { -class GR_CORE_API gri_glfsr -{ - private: - int d_shift_register; - int d_mask; + class FILTER_API @IMPL_NAME@ : public @BASE_NAME@ + { + private: + kernel::@BASE_NAME@ *d_fir; + bool d_updated; - public: + public: + @IMPL_NAME@(int decimation, const std::vector<@TAP_TYPE@> &taps); - gri_glfsr(int mask, int seed) { d_shift_register = seed; d_mask = mask; } - static int glfsr_mask(int degree); + ~@IMPL_NAME@(); - unsigned char next_bit() { - unsigned char bit = d_shift_register & 1; - d_shift_register >>= 1; - if (bit) - d_shift_register ^= d_mask; - return bit; - } + void set_taps(const std::vector<@TAP_TYPE@> &taps); + std::vector<@TAP_TYPE@> taps() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; - int mask() const { return d_mask; } -}; + } /* namespace filter */ +} /* namespace gr */ -#endif /* INCLUDED_GRI_GLFSR_H */
\ No newline at end of file +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/lib/fir_filter_with_buffer.cc b/gr-filter/lib/fir_filter_with_buffer.cc new file mode 100644 index 0000000000..7a35a92252 --- /dev/null +++ b/gr-filter/lib/fir_filter_with_buffer.cc @@ -0,0 +1,496 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <filter/fir_filter_with_buffer.h> +#include <fft/fft.h> +#include <volk/volk.h> +#include <algorithm> +#include <cstdio> +#include <cstring> + +namespace gr { + namespace filter { + namespace kernel { + + fir_filter_with_buffer_fff::fir_filter_with_buffer_fff(const std::vector<float> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(float); + + d_buffer_ptr = NULL; + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_float(1); + } + + fir_filter_with_buffer_fff::~fir_filter_with_buffer_fff() + { + if(d_buffer_ptr != NULL) { + fft::free(d_buffer_ptr); + d_buffer_ptr = NULL; + } + + // Free aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_with_buffer_fff::set_taps(const std::vector<float> &taps) + { + if(d_buffer_ptr != NULL) { + fft::free(d_buffer_ptr); + d_buffer_ptr = NULL; + } + + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // We allocate enough to be able to look back and forth + // d_naligned beyond the buffer boundaries and make sure these + // are zeroed out (or they may be nan, which will cause + // problems). We then set d_buffer to the position in the + // d_buffer_ptr such that we only touch the internally + // allocated space. + d_buffer_ptr = fft::malloc_float(2*(d_ntaps + d_naligned)); + memset(d_buffer_ptr, 0, 2*(d_ntaps + d_naligned)*sizeof(float)); + d_buffer = d_buffer_ptr + d_naligned; + + // Allocate aligned taps + d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + + d_idx = 0; + } + + std::vector<float> + fir_filter_with_buffer_fff::taps() const + { + std::vector<float> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + float + fir_filter_with_buffer_fff::filter(float input) + { + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + + const float *ar = (float*)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1)); + unsigned al = (&d_buffer[d_idx]) - ar; + + volk_32f_x2_dot_prod_32f_a(d_output, ar, + d_aligned_taps[al], + ntaps()+al); + return *d_output; + } + + float + fir_filter_with_buffer_fff::filter(const float input[], + unsigned long dec) + { + unsigned int i; + + for(i = 0; i < dec; i++) { + d_buffer[d_idx] = input[i]; + d_buffer[d_idx+ntaps()] = input[i]; + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + } + + const float *ar = (float*)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1)); + unsigned al = (&d_buffer[d_idx]) - ar; + + volk_32f_x2_dot_prod_32f_a(d_output, ar, + d_aligned_taps[al], + ntaps()+al); + return *d_output; + } + + void + fir_filter_with_buffer_fff::filterN(float output[], + const float input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } + } + + void + fir_filter_with_buffer_fff::filterNdec(float output[], + const float input[], + unsigned long n, + unsigned long decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[j], decimate); + j += decimate; + } + } + + + /**************************************************************/ + + + fir_filter_with_buffer_ccc::fir_filter_with_buffer_ccc(const std::vector<gr_complex> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(gr_complex); + + d_buffer_ptr = NULL; + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_complex(1); + } + + fir_filter_with_buffer_ccc::~fir_filter_with_buffer_ccc() + { + if(d_buffer_ptr != NULL) { + fft::free(d_buffer_ptr); + d_buffer_ptr = NULL; + } + + // Free aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_with_buffer_ccc::set_taps(const std::vector<gr_complex> &taps) + { + if(d_buffer_ptr != NULL) { + fft::free(d_buffer_ptr); + d_buffer_ptr = NULL; + } + + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // We allocate enough to be able to look back and forth + // d_naligned beyond the buffer boundaries and make sure these + // are zeroed out (or they may be nan, which will cause + // problems). We then set d_buffer to the position in the + // d_buffer_ptr such that we only touch the internally + // allocated space. + d_buffer_ptr = fft::malloc_complex(2*(d_ntaps + d_naligned)); + memset(d_buffer_ptr, 0, 2*(d_ntaps + d_naligned)*sizeof(gr_complex)); + d_buffer = d_buffer_ptr + d_naligned; + + // Allocate aligned taps + d_aligned_taps = (gr_complex**)malloc(d_naligned*sizeof(gr_complex**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_complex(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(gr_complex)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + + d_idx = 0; + } + + std::vector<gr_complex> + fir_filter_with_buffer_ccc::taps() const + { + std::vector<gr_complex> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + gr_complex + fir_filter_with_buffer_ccc::filter(gr_complex input) + { + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + + const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1)); + unsigned al = (&d_buffer[d_idx]) - ar; + + volk_32fc_x2_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + (ntaps()+al)*sizeof(gr_complex)); + return *d_output; + } + + gr_complex + fir_filter_with_buffer_ccc::filter(const gr_complex input[], + unsigned long dec) + { + unsigned int i; + + for(i = 0; i < dec; i++) { + d_buffer[d_idx] = input[i]; + d_buffer[d_idx+ntaps()] = input[i]; + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + } + + const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1)); + unsigned al = (&d_buffer[d_idx]) - ar; + + volk_32fc_x2_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + (ntaps()+al)*sizeof(gr_complex)); + return *d_output; + } + + void + fir_filter_with_buffer_ccc::filterN(gr_complex output[], + const gr_complex input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } + } + + void + fir_filter_with_buffer_ccc::filterNdec(gr_complex output[], + const gr_complex input[], + unsigned long n, + unsigned long decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[j], decimate); + j += decimate; + } + } + + + /**************************************************************/ + + + fir_filter_with_buffer_ccf::fir_filter_with_buffer_ccf(const std::vector<float> &taps) + { + d_align = volk_get_alignment(); + d_naligned = d_align / sizeof(gr_complex); + + d_buffer_ptr = NULL; + d_aligned_taps = NULL; + set_taps(taps); + + // Make sure the output sample is always aligned, too. + d_output = fft::malloc_complex(1); + } + + fir_filter_with_buffer_ccf::~fir_filter_with_buffer_ccf() + { + if(d_buffer_ptr != NULL) { + fft::free(d_buffer_ptr); + d_buffer_ptr = NULL; + } + + // Free aligned taps + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + // Free output sample + fft::free(d_output); + } + + void + fir_filter_with_buffer_ccf::set_taps(const std::vector<float> &taps) + { + if(d_buffer_ptr != NULL) { + fft::free(d_buffer_ptr); + d_buffer_ptr = NULL; + } + + // Free the taps if already allocated + if(d_aligned_taps != NULL) { + for(int i = 0; i < d_naligned; i++) { + fft::free(d_aligned_taps[i]); + } + fft::free(d_aligned_taps); + d_aligned_taps = NULL; + } + + d_ntaps = (int)taps.size(); + d_taps = taps; + std::reverse(d_taps.begin(), d_taps.end()); + + // We allocate enough to be able to look back and forth + // d_naligned beyond the buffer boundaries and make sure these + // are zeroed out (or they may be nan, which will cause + // problems). We then set d_buffer to the position in the + // d_buffer_ptr such that we only touch the internally + // allocated space. + d_buffer_ptr = fft::malloc_complex(2*(d_ntaps + d_naligned)); + memset(d_buffer_ptr, 0, 2*(d_ntaps + d_naligned)*sizeof(gr_complex)); + d_buffer = d_buffer_ptr + d_naligned; + + // Allocate aligned taps + d_aligned_taps = (float**)malloc(d_naligned*sizeof(float**)); + for(int i = 0; i < d_naligned; i++) { + d_aligned_taps[i] = fft::malloc_float(d_ntaps+d_naligned-1); + memset(d_aligned_taps[i], 0, sizeof(float)*(d_ntaps+d_naligned-1)); + for(unsigned int j = 0; j < d_ntaps; j++) + d_aligned_taps[i][i+j] = d_taps[j]; + } + + d_idx = 0; + } + + std::vector<float> + fir_filter_with_buffer_ccf::taps() const + { + std::vector<float> t = d_taps; + std::reverse(t.begin(), t.end()); + return t; + } + + gr_complex + fir_filter_with_buffer_ccf::filter(gr_complex input) + { + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + + const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1)); + unsigned al = (&d_buffer[d_idx]) - ar; + + volk_32fc_32f_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + ntaps()+al); + return *d_output; + } + + gr_complex + fir_filter_with_buffer_ccf::filter(const gr_complex input[], + unsigned long dec) + { + unsigned int i; + + for(i = 0; i < dec; i++) { + d_buffer[d_idx] = input[i]; + d_buffer[d_idx+ntaps()] = input[i]; + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + } + + const gr_complex *ar = (gr_complex *)((unsigned long)(&d_buffer[d_idx]) & ~(d_align-1)); + unsigned al = (&d_buffer[d_idx]) - ar; + + volk_32fc_32f_dot_prod_32fc_a(d_output, ar, + d_aligned_taps[al], + ntaps()+al); + return *d_output; + } + + void + fir_filter_with_buffer_ccf::filterN(gr_complex output[], + const gr_complex input[], + unsigned long n) + { + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } + } + + void + fir_filter_with_buffer_ccf::filterNdec(gr_complex output[], + const gr_complex input[], + unsigned long n, + unsigned long decimate) + { + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[j], decimate); + j += decimate; + } + } + + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/firdes.cc b/gr-filter/lib/firdes.cc new file mode 100644 index 0000000000..5c3320d71a --- /dev/null +++ b/gr-filter/lib/firdes.cc @@ -0,0 +1,855 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2007,2008,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <filter/firdes.h> +#include <stdexcept> + +using std::vector; + +namespace gr { + namespace filter { + +#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */ + + static double Izero(double x) + { + double sum, u, halfx, temp; + int n; + + sum = u = n = 1; + halfx = x/2.0; + do { + temp = halfx/(double)n; + n += 1; + temp *= temp; + u *= temp; + sum += u; + } while (u >= IzeroEPSILON*sum); + return(sum); + } + + + // + // === Low Pass === + // + + vector<float> + firdes::low_pass_2(double gain, + double sampling_freq, // Hz + double cutoff_freq, // Hz BEGINNING of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_1f(sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes(sampling_freq, + transition_width, + attenuation_dB); + + // construct the truncated ideal impulse response + // [sin(x)/x for the low pass case] + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + for(int n = -M; n <= M; n++) { + if (n == 0) + taps[n + M] = fwT0 / M_PI * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = sin(n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For low-pass, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + vector<float> + firdes::low_pass(double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_1f(sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps(sampling_freq, + transition_width, + window_type, beta); + + // construct the truncated ideal impulse response + // [sin(x)/x for the low pass case] + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if(n == 0) + taps[n + M] = fwT0 / M_PI * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = sin(n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For low-pass, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + + // + // === High Pass === + // + + vector<float> + firdes::high_pass_2(double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_1f(sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes(sampling_freq, + transition_width, + attenuation_dB); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if(n == 0) + taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = -sin(n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For high-pass, gain @ fs/2 freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos(n * M_PI); + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + + vector<float> + firdes::high_pass(double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_1f(sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps(sampling_freq, + transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if(n == 0) + taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = -sin(n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For high-pass, gain @ fs/2 freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos(n * M_PI); + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + // + // === Band Pass === + // + + vector<float> + firdes::band_pass_2(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_2f(sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes(sampling_freq, + transition_width, + attenuation_dB); + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if (n == 0) + taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M]; + else { + taps[n + M] = (sin(n * fwT1) - sin(n * fwT0)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-pass, gain @ center freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos(n * (fwT0 + fwT1) * 0.5); + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + + vector<float> + firdes::band_pass(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_2f(sampling_freq, + low_cutoff_freq, + high_cutoff_freq, + transition_width); + + int ntaps = compute_ntaps(sampling_freq, + transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if (n == 0) + taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M]; + else { + taps[n + M] = (sin(n * fwT1) - sin(n * fwT0)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-pass, gain @ center freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos(n * (fwT0 + fwT1) * 0.5); + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + // + // === Complex Band Pass === + // + + vector<gr_complex> + firdes::complex_band_pass_2(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_2f_c(sampling_freq, + low_cutoff_freq, + high_cutoff_freq, + transition_width); + + int ntaps = compute_ntaps_windes(sampling_freq, + transition_width, + attenuation_dB); + + vector<gr_complex> taps(ntaps); + vector<float> lptaps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + lptaps = low_pass_2(gain, sampling_freq, + (high_cutoff_freq - low_cutoff_freq)/2, + transition_width, attenuation_dB, + window_type, beta); + + gr_complex *optr = &taps[0]; + float *iptr = &lptaps[0]; + float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq; + float phase = 0; + if (lptaps.size() & 01) { + phase = - freq * ( lptaps.size() >> 1 ); + } + else + phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1); + + for(unsigned int i = 0; i < lptaps.size(); i++) { + *optr++ = gr_complex(*iptr * cos(phase), *iptr * sin(phase)); + iptr++, phase += freq; + } + + return taps; + } + + + vector<gr_complex> + firdes::complex_band_pass(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_2f_c (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, + transition_width); + + int ntaps = compute_ntaps(sampling_freq, + transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<gr_complex> taps(ntaps); + vector<float> lptaps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + lptaps = low_pass(gain, sampling_freq, + (high_cutoff_freq - low_cutoff_freq)/2, + transition_width, window_type, beta); + + gr_complex *optr = &taps[0]; + float *iptr = &lptaps[0]; + float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq; + float phase = 0; + if(lptaps.size() & 01) { + phase = - freq * ( lptaps.size() >> 1 ); + } + else + phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1); + + for(unsigned int i=0;i<lptaps.size();i++) { + *optr++ = gr_complex(*iptr * cos(phase), *iptr * sin(phase)); + iptr++, phase += freq; + } + + return taps; + } + + // + // === Band Reject === + // + + vector<float> + firdes::band_reject_2(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_2f(sampling_freq, + low_cutoff_freq, + high_cutoff_freq, + transition_width); + + int ntaps = compute_ntaps_windes(sampling_freq, + transition_width, + attenuation_dB); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if (n == 0) + taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]); + else { + taps[n + M] = (sin(n * fwT0) - sin(n * fwT1)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-reject, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + vector<float> + firdes::band_reject(double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser + { + sanity_check_2f(sampling_freq, + low_cutoff_freq, + high_cutoff_freq, + transition_width); + + int ntaps = compute_ntaps(sampling_freq, + transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window(window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for(int n = -M; n <= M; n++) { + if (n == 0) + taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]); + else { + taps[n + M] = (sin(n * fwT0) - sin(n * fwT1)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-reject, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for(int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for(int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; + } + + // + // Hilbert Transform + // + + vector<float> + firdes::hilbert(unsigned int ntaps, + win_type windowtype, + double beta) + { + if(!(ntaps & 1)) + throw std::out_of_range("Hilbert: Must have odd number of taps"); + + vector<float> taps(ntaps); + vector<float> w = window (windowtype, ntaps, beta); + unsigned int h = (ntaps-1)/2; + float gain=0; + for(unsigned int i = 1; i <= h; i++) { + if(i & 1) { + float x = 1/(float)i; + taps[h+i] = x * w[h+i]; + taps[h-i] = -x * w[h-i]; + gain = taps[h+i] - gain; + } + else + taps[h+i] = taps[h-i] = 0; + } + + gain = 2 * fabs(gain); + for(unsigned int i = 0; i < ntaps; i++) + taps[i] /= gain; + return taps; + } + + // + // Gaussian + // + + vector<float> + firdes::gaussian(double gain, + double spb, + double bt, + int ntaps) + { + vector<float> taps(ntaps); + double scale = 0; + double dt = 1.0/spb; + double s = 1.0/(sqrt(log(2.0)) / (2*M_PI*bt)); + double t0 = -0.5 * ntaps; + double ts; + for(int i=0;i<ntaps;i++) { + t0++; + ts = s*dt*t0; + taps[i] = exp(-0.5*ts*ts); + scale += taps[i]; + } + for(int i=0;i<ntaps;i++) + taps[i] = taps[i] / scale * gain; + + return taps; + } + + + // + // Root Raised Cosine + // + + vector<float> + firdes::root_raised_cosine(double gain, + double sampling_freq, + double symbol_rate, + double alpha, + int ntaps) + { + ntaps |= 1; // ensure that ntaps is odd + + double spb = sampling_freq/symbol_rate; // samples per bit/symbol + vector<float> taps(ntaps); + double scale = 0; + for(int i = 0; i < ntaps; i++) { + double x1,x2,x3,num,den; + double xindx = i - ntaps/2; + x1 = M_PI * xindx/spb; + x2 = 4 * alpha * xindx / spb; + x3 = x2*x2 - 1; + + if(fabs(x3) >= 0.000001) { // Avoid Rounding errors... + if(i != ntaps/2) + num = cos((1+alpha)*x1) + sin((1-alpha)*x1)/(4*alpha*xindx/spb); + else + num = cos((1+alpha)*x1) + (1-alpha) * M_PI / (4*alpha); + den = x3 * M_PI; + } + else { + if(alpha==1) { + taps[i] = -1; + continue; + } + x3 = (1-alpha)*x1; + x2 = (1+alpha)*x1; + num = (sin(x2)*(1+alpha)*M_PI + - cos(x3)*((1-alpha)*M_PI*spb)/(4*alpha*xindx) + + sin(x3)*spb*spb/(4*alpha*xindx*xindx)); + den = -32 * M_PI * alpha * alpha * xindx/spb; + } + taps[i] = 4 * alpha * num / den; + scale += taps[i]; + } + + for(int i = 0; i < ntaps; i++) + taps[i] = taps[i] * gain / scale; + + return taps; + } + + // + // === Utilities === + // + + // delta_f / width_factor gives number of taps required. + static const float width_factor[5] = { // indexed by win_type + 3.3, // WIN_HAMMING + 3.1, // WIN_HANN + 5.5, // WIN_BLACKMAN + 2.0, // WIN_RECTANGULAR + //5.0 // WIN_KAISER (guesstimate compromise) + //2.0 // WIN_KAISER (guesstimate compromise) + 10.0 // WIN_KAISER + }; + + int + firdes::compute_ntaps_windes(double sampling_freq, + double transition_width, // this is frequency, not relative frequency + double attenuation_dB) + { + // Based on formula from Multirate Signal Processing for + // Communications Systems, fredric j harris + int ntaps = (int)(attenuation_dB*sampling_freq/(22.0*transition_width)); + if ((ntaps & 1) == 0) // if even... + ntaps++; // ...make odd + return ntaps; + } + + int + firdes::compute_ntaps(double sampling_freq, + double transition_width, + win_type window_type, + double beta) + { + // normalized transition width + double delta_f = transition_width / sampling_freq; + + // compute number of taps required for given transition width + int ntaps = (int)(width_factor[window_type] / delta_f + 0.5); + if((ntaps & 1) == 0) // if even... + ntaps++; // ...make odd + + return ntaps; + } + + double + firdes::bessi0(double x) + { + double ax,ans; + double y; + + ax=fabs(x); + if (ax < 3.75) { + y=x/3.75; + y*=y; + ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 + +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2))))); + } + else { + y=3.75/ax; + ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 + +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 + +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 + +y*0.392377e-2)))))))); + } + return ans; + } + + vector<float> + firdes::window (win_type type, int ntaps, double beta) + { + vector<float> taps(ntaps); + int M = ntaps - 1; // filter order + + switch (type) { + case WIN_RECTANGULAR: + for(int n = 0; n < ntaps; n++) + taps[n] = 1; + + case WIN_HAMMING: + for(int n = 0; n < ntaps; n++) + taps[n] = 0.54 - 0.46 * cos((2 * M_PI * n) / M); + break; + + case WIN_HANN: + for(int n = 0; n < ntaps; n++) + taps[n] = 0.5 - 0.5 * cos((2 * M_PI * n) / M); + break; + + case WIN_BLACKMAN: + for(int n = 0; n < ntaps; n++) + taps[n] = 0.42 - 0.50 * cos((2*M_PI * n) / (M-1)) + - 0.08 * cos((4*M_PI * n) / (M-1)); + break; + + case WIN_BLACKMAN_hARRIS: + for(int n = -ntaps/2; n < ntaps/2; n++) + taps[n+ntaps/2] = 0.35875 + 0.48829*cos((2*M_PI * n) / (float)M) + + 0.14128*cos((4*M_PI * n) / (float)M) + 0.01168*cos((6*M_PI * n) / (float)M); + break; + + case WIN_KAISER: + { + double IBeta = 1.0/Izero(beta); + double inm1 = 1.0/((double)(ntaps)); + double temp; + //fprintf(stderr, "IBeta = %g; inm1 = %g\n", IBeta, inm1); + + for(int i=0; i<ntaps; i++) { + temp = i * inm1; + //fprintf(stderr, "temp = %g\n", temp); + taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta; + //fprintf(stderr, "taps[%d] = %g\n", i, taps[i]); + } + } + break; + + default: + throw std::out_of_range("firdes:window: type out of range"); + } + + return taps; + } + + void + firdes::sanity_check_1f(double sampling_freq, + double fa, // cutoff freq + double transition_width) + { + if(sampling_freq <= 0.0) + throw std::out_of_range("firdes check failed: sampling_freq > 0"); + + if(fa <= 0.0 || fa > sampling_freq / 2) + throw std::out_of_range("firdes check failed: 0 < fa <= sampling_freq / 2"); + + if(transition_width <= 0) + throw std::out_of_range("gr_dirdes check failed: transition_width > 0"); + } + + void + firdes::sanity_check_2f(double sampling_freq, + double fa, // first cutoff freq + double fb, // second cutoff freq + double transition_width) + { + if (sampling_freq <= 0.0) + throw std::out_of_range("firdes check failed: sampling_freq > 0"); + + if (fa <= 0.0 || fa > sampling_freq / 2) + throw std::out_of_range("firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (fb <= 0.0 || fb > sampling_freq / 2) + throw std::out_of_range("firdes check failed: 0 < fb <= sampling_freq / 2"); + + if (fa > fb) + throw std::out_of_range("firdes check failed: fa <= fb"); + + if (transition_width <= 0) + throw std::out_of_range("firdes check failed: transition_width > 0"); + } + + void + firdes::sanity_check_2f_c(double sampling_freq, + double fa, // first cutoff freq + double fb, // second cutoff freq + double transition_width) + { + if(sampling_freq <= 0.0) + throw std::out_of_range("firdes check failed: sampling_freq > 0"); + + if(fa < -sampling_freq / 2 || fa > sampling_freq / 2) + throw std::out_of_range("firdes check failed: 0 < fa <= sampling_freq / 2"); + + if(fb < -sampling_freq / 2 || fb > sampling_freq / 2) + throw std::out_of_range("firdes check failed: 0 < fb <= sampling_freq / 2"); + + if(fa > fb) + throw std::out_of_range("firdes check failed: fa <= fb"); + + if(transition_width <= 0) + throw std::out_of_range("firdes check failed: transition_width > 0"); + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fractional_interpolator_cc_impl.cc b/gr-filter/lib/fractional_interpolator_cc_impl.cc new file mode 100644 index 0000000000..8fd89f437f --- /dev/null +++ b/gr-filter/lib/fractional_interpolator_cc_impl.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "fractional_interpolator_cc_impl.h" +#include <stdexcept> + +namespace gr { + namespace filter { + + fractional_interpolator_cc::sptr + fractional_interpolator_cc::make(float phase_shift, float interp_ratio) + { + return gnuradio::get_initial_sptr( + new fractional_interpolator_cc_impl(phase_shift, interp_ratio)); + } + + fractional_interpolator_cc_impl::fractional_interpolator_cc_impl + (float phase_shift, float interp_ratio) + : gr_block("fractional_interpolator_cc", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))), + d_mu (phase_shift), d_mu_inc (interp_ratio), + d_interp(new mmse_fir_interpolator_cc()) + { + if(interp_ratio <= 0) + throw std::out_of_range("interpolation ratio must be > 0"); + if(phase_shift < 0 || phase_shift > 1) + throw std::out_of_range("phase shift ratio must be > 0 and < 1"); + + set_relative_rate(1.0 / interp_ratio); + } + + fractional_interpolator_cc_impl::~fractional_interpolator_cc_impl() + { + delete d_interp; + } + + void + fractional_interpolator_cc_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i=0; i < ninputs; i++) { + ninput_items_required[i] = + (int)ceil((noutput_items * d_mu_inc) + d_interp->ntaps()); + } + } + + int + fractional_interpolator_cc_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex*)input_items[0]; + gr_complex *out = (gr_complex*)output_items[0]; + + int ii = 0; // input index + int oo = 0; // output index + + while(oo < noutput_items) { + out[oo++] = d_interp->interpolate(&in[ii], d_mu); + + double s = d_mu + d_mu_inc; + double f = floor(s); + int incr = (int)f; + d_mu = s - f; + ii += incr; + } + + consume_each(ii); + + return noutput_items; + } + + float + fractional_interpolator_cc_impl::mu() const + { + return d_mu; + } + + float + fractional_interpolator_cc_impl::interp_ratio() const + { + return d_mu_inc; + } + + void + fractional_interpolator_cc_impl::set_mu(float mu) + { + d_mu = mu; + } + + void + fractional_interpolator_cc_impl::set_interp_ratio(float interp_ratio) + { + d_mu_inc = interp_ratio; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fractional_interpolator_cc_impl.h b/gr-filter/lib/fractional_interpolator_cc_impl.h new file mode 100644 index 0000000000..cb42186038 --- /dev/null +++ b/gr-filter/lib/fractional_interpolator_cc_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_CC_IMPL_H +#define INCLUDED_FRACTIONAL_INTERPOLATOR_CC_IMPL_H + +#include <filter/fractional_interpolator_cc.h> +#include <filter/mmse_fir_interpolator_cc.h> + +namespace gr { + namespace filter { + + class FILTER_API fractional_interpolator_cc_impl + : public fractional_interpolator_cc + { + private: + float d_mu; + float d_mu_inc; + mmse_fir_interpolator_cc *d_interp; + + public: + fractional_interpolator_cc_impl(float phase_shift, + float interp_ratio); + ~fractional_interpolator_cc_impl(); + + void forecast(int noutput_items, + gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + float mu() const; + float interp_ratio() const; + void set_mu(float mu); + void set_interp_ratio(float interp_ratio); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_CC_IMPL_H */ diff --git a/gr-filter/lib/fractional_interpolator_ff_impl.cc b/gr-filter/lib/fractional_interpolator_ff_impl.cc new file mode 100644 index 0000000000..6b35dc1061 --- /dev/null +++ b/gr-filter/lib/fractional_interpolator_ff_impl.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include "fractional_interpolator_ff_impl.h" +#include <stdexcept> + +namespace gr { + namespace filter { + + fractional_interpolator_ff::sptr + fractional_interpolator_ff::make(float phase_shift, float interp_ratio) + { + return gnuradio::get_initial_sptr( + new fractional_interpolator_ff_impl(phase_shift, interp_ratio)); + } + + fractional_interpolator_ff_impl::fractional_interpolator_ff_impl + (float phase_shift, float interp_ratio) + : gr_block("fractional_interpolator_ff", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_mu (phase_shift), d_mu_inc (interp_ratio), + d_interp(new mmse_fir_interpolator_ff()) + { + if(interp_ratio <= 0) + throw std::out_of_range("interpolation ratio must be > 0"); + if(phase_shift < 0 || phase_shift > 1) + throw std::out_of_range("phase shift ratio must be > 0 and < 1"); + + set_relative_rate(1.0 / interp_ratio); + } + + fractional_interpolator_ff_impl::~fractional_interpolator_ff_impl() + { + delete d_interp; + } + + void + fractional_interpolator_ff_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i=0; i < ninputs; i++) { + ninput_items_required[i] = + (int)ceil((noutput_items * d_mu_inc) + d_interp->ntaps()); + } + } + + int + fractional_interpolator_ff_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float*)input_items[0]; + float *out = (float*)output_items[0]; + + int ii = 0; // input index + int oo = 0; // output index + + while(oo < noutput_items) { + out[oo++] = d_interp->interpolate(&in[ii], d_mu); + + double s = d_mu + d_mu_inc; + double f = floor(s); + int incr = (int)f; + d_mu = s - f; + ii += incr; + } + + consume_each(ii); + + return noutput_items; + } + + float + fractional_interpolator_ff_impl::mu() const + { + return d_mu; + } + + float + fractional_interpolator_ff_impl::interp_ratio() const + { + return d_mu_inc; + } + + void + fractional_interpolator_ff_impl::set_mu(float mu) + { + d_mu = mu; + } + + void + fractional_interpolator_ff_impl::set_interp_ratio(float interp_ratio) + { + d_mu_inc = interp_ratio; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/fractional_interpolator_ff_impl.h b/gr-filter/lib/fractional_interpolator_ff_impl.h new file mode 100644 index 0000000000..d31385cc49 --- /dev/null +++ b/gr-filter/lib/fractional_interpolator_ff_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FRACTIONAL_INTERPOLATOR_FF_IMPL_H +#define INCLUDED_FRACTIONAL_INTERPOLATOR_FF_IMPL_H + +#include <filter/fractional_interpolator_ff.h> +#include <filter/mmse_fir_interpolator_ff.h> + +namespace gr { + namespace filter { + + class FILTER_API fractional_interpolator_ff_impl + : public fractional_interpolator_ff + { + private: + float d_mu; + float d_mu_inc; + mmse_fir_interpolator_ff *d_interp; + + public: + fractional_interpolator_ff_impl(float phase_shift, + float interp_ratio); + ~fractional_interpolator_ff_impl(); + + void forecast(int noutput_items, + gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + float mu() const; + float interp_ratio() const; + void set_mu(float mu); + void set_interp_ratio(float interp_ratio); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FRACTIONAL_INTERPOLATOR_FF_IMPL_H */ diff --git a/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t new file mode 100644 index 0000000000..a59fa12b36 --- /dev/null +++ b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.cc.t @@ -0,0 +1,143 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * WARNING: This file is automatically generated by cmake. + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "@IMPL_NAME@.h" +#include <gr_io_signature.h> +#include <volk/volk.h> + +namespace gr { + namespace filter { + + @BASE_NAME@::sptr + @BASE_NAME@::make(int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, + double sampling_freq) + { + return gnuradio::get_initial_sptr(new @IMPL_NAME@ + (decimation, taps, + center_freq, + sampling_freq)); + } + + @IMPL_NAME@::@IMPL_NAME@(int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, + double sampling_freq) + : gr_sync_decimator("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@)), + decimation), + d_proto_taps(taps), d_center_freq(center_freq), + d_sampling_freq(sampling_freq), + d_updated(false) + { + std::vector<gr_complex> dummy_taps; + d_composite_fir = new kernel::@CFIR_TYPE@(decimation, dummy_taps); + + set_history(d_proto_taps.size()); + build_composite_fir(); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + delete d_composite_fir; + } + + void + @IMPL_NAME@::build_composite_fir() + { + std::vector<gr_complex> ctaps(d_proto_taps.size()); + + float fwT0 = -2 * M_PI * d_center_freq / d_sampling_freq; + for(unsigned int i = 0; i < d_proto_taps.size(); i++) { + ctaps[i] = d_proto_taps[i] * exp(gr_complex(0, i * fwT0)); + } + + std::reverse(ctaps.begin(), ctaps.end()); + d_composite_fir->set_taps(ctaps); + d_r.set_phase_incr(exp(gr_complex(0, fwT0 * decimation()))); + } + + void + @IMPL_NAME@::set_center_freq(double center_freq) + { + d_center_freq = center_freq; + d_updated = true; + } + + double + @IMPL_NAME@::center_freq() const + { + return d_center_freq; + } + + void + @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps) + { + d_proto_taps = taps; + d_updated = true; + } + + std::vector<@TAP_TYPE@> + @IMPL_NAME@::taps() const + { + return d_proto_taps; + } + + int + @IMPL_NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + @I_TYPE@ *in = (@I_TYPE@ *)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *)output_items[0]; + + // rebuild composite FIR if the center freq has changed + if(d_updated) { + set_history(d_proto_taps.size()); + build_composite_fir(); + d_updated = false; + return 0; // history requirements may have changed. + } + + unsigned j = 0; + for (int i = 0; i < noutput_items; i++){ + out[i] = d_r.rotate(d_composite_fir->filter(&in[j])); + j += decimation(); + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ + diff --git a/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t new file mode 100644 index 0000000000..0cf976d582 --- /dev/null +++ b/gr-filter/lib/freq_xlating_fir_filter_XXX_impl.h.t @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * WARNING: This file is automatically generated by cmake. + * Any changes made to this file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/api.h> +#include <filter/fir_filter.h> +#include <filter/@BASE_NAME@.h> + +namespace gr { + namespace filter { + + class FILTER_API @IMPL_NAME@ : public @BASE_NAME@ + { + protected: + std::vector<@TAP_TYPE@> d_proto_taps; + kernel::@CFIR_TYPE@ *d_composite_fir; + gr_rotator d_r; + double d_center_freq; + double d_sampling_freq; + bool d_updated; + + virtual void build_composite_fir(); + public: + + @IMPL_NAME@(int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, + double sampling_freq); + virtual ~@IMPL_NAME@(); + + void set_center_freq(double center_freq); + double center_freq() const; + + void set_taps(const std::vector<@TAP_TYPE@> &taps); + std::vector<@TAP_TYPE@> taps() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/lib/hilbert_fc_impl.cc b/gr-filter/lib/hilbert_fc_impl.cc new file mode 100644 index 0000000000..52b2dabae9 --- /dev/null +++ b/gr-filter/lib/hilbert_fc_impl.cc @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "hilbert_fc_impl.h" +#include <filter/firdes.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +namespace gr { + namespace filter { + + hilbert_fc::sptr hilbert_fc::make(unsigned int ntaps) + { + return gnuradio::get_initial_sptr(new hilbert_fc_impl(ntaps)); + } + + hilbert_fc_impl::hilbert_fc_impl(unsigned int ntaps) + : gr_sync_block ("hilbert_fc", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(gr_complex))), + d_ntaps(ntaps | 0x1) // ensure ntaps is odd + { + d_hilb = new kernel::fir_filter_fff(1, firdes::hilbert(d_ntaps)); + set_history (d_ntaps); + + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1, alignment_multiple)); + } + + hilbert_fc_impl::~hilbert_fc_impl() + { + delete d_hilb; + } + + int + hilbert_fc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + float *in = (float *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + for(int i = 0; i < noutput_items; i++) { + out[i] = gr_complex(in[i + d_ntaps/2], + d_hilb->filter(&in[i])); + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/hilbert_fc_impl.h b/gr-filter/lib/hilbert_fc_impl.h new file mode 100644 index 0000000000..d2b41b5732 --- /dev/null +++ b/gr-filter/lib/hilbert_fc_impl.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_HILBERT_FC_IMPL_H +#define INCLUDED_FILTER_HILBERT_FC_IMPL_H + +#include <filter/hilbert_fc.h> +#include <filter/fir_filter.h> +#include <gr_types.h> + +namespace gr { + namespace filter { + + class FILTER_API hilbert_fc_impl : public hilbert_fc + { + private: + unsigned int d_ntaps; + kernel::fir_filter_fff *d_hilb; + + public: + hilbert_fc_impl(unsigned int ntaps); + + ~hilbert_fc_impl(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_FILTER_HILBERT_FC_IMPL_H */ diff --git a/gr-filter/lib/iir_filter_ffd_impl.cc b/gr-filter/lib/iir_filter_ffd_impl.cc new file mode 100644 index 0000000000..24bfad1908 --- /dev/null +++ b/gr-filter/lib/iir_filter_ffd_impl.cc @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "iir_filter_ffd_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + iir_filter_ffd::sptr + iir_filter_ffd::make(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) + { + return gnuradio::get_initial_sptr(new iir_filter_ffd_impl(fftaps, fbtaps)); + } + + iir_filter_ffd_impl::iir_filter_ffd_impl(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) + + : gr_sync_block("iir_filter_ffd", + gr_make_io_signature(1, 1, sizeof (float)), + gr_make_io_signature(1, 1, sizeof (float))), + d_updated(false) + { + d_iir = new kernel::iir_filter<float,float,double>(fftaps, fbtaps); + //d_iir = new gri_iir<float,float,double>(fftaps, fbtaps); + } + + iir_filter_ffd_impl::~iir_filter_ffd_impl() + { + delete d_iir; + } + + void + iir_filter_ffd_impl::set_taps(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) + { + d_new_fftaps = fftaps; + d_new_fbtaps = fbtaps; + d_updated = true; + } + + int + iir_filter_ffd_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float*)input_items[0]; + float *out = (float*)output_items[0]; + + if(d_updated) { + d_iir->set_taps(d_new_fftaps, d_new_fbtaps); + d_updated = false; + } + + d_iir->filter_n(out, in, noutput_items); + return noutput_items; + }; + + } /* namespace filter */ +} /* namespace gr */ + diff --git a/gr-filter/lib/iir_filter_ffd_impl.h b/gr-filter/lib/iir_filter_ffd_impl.h new file mode 100644 index 0000000000..45aab6c227 --- /dev/null +++ b/gr-filter/lib/iir_filter_ffd_impl.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_IIR_FILTER_FFD_IMPL_H +#define INCLUDED_IIR_FILTER_FFD_IMPL_H + +#include <filter/iir_filter.h> +#include <filter/iir_filter_ffd.h> + +namespace gr { + namespace filter { + + class FILTER_API iir_filter_ffd_impl : public iir_filter_ffd + { + private: + bool d_updated; + kernel::iir_filter<float,float,double> *d_iir; + std::vector<double> d_new_fftaps; + std::vector<double> d_new_fbtaps; + + public: + iir_filter_ffd_impl(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps); + ~iir_filter_ffd_impl(); + + void set_taps(const std::vector<double> &fftaps, + const std::vector<double> &fbtaps); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_IIR_FILTER_FFD_IMPL_H */ diff --git a/gr-filter/lib/interp_fir_filter_XXX_impl.cc.t b/gr-filter/lib/interp_fir_filter_XXX_impl.cc.t new file mode 100644 index 0000000000..c9127d7379 --- /dev/null +++ b/gr-filter/lib/interp_fir_filter_XXX_impl.cc.t @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "@IMPL_NAME@.h" +#include <gr_io_signature.h> +#include <volk/volk.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + @BASE_NAME@::sptr + @BASE_NAME@::make(unsigned interpolation, + const std::vector<@TAP_TYPE@> &taps) + { + return gnuradio::get_initial_sptr(new @IMPL_NAME@ + (interpolation, taps)); + } + + @IMPL_NAME@::@IMPL_NAME@(unsigned interpolation, + const std::vector<@TAP_TYPE@> &taps) + : gr_sync_interpolator("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@)), + interpolation), + d_updated(false), d_firs(interpolation) + { + if(interpolation == 0) { + throw std::out_of_range("@IMPL_NAME@: interpolation must be > 0\n"); + } + + std::vector<@TAP_TYPE@> dummy_taps; + + for(unsigned i = 0; i < interpolation; i++) { + d_firs[i] = new kernel::@FIR_TYPE@(1, dummy_taps); + } + + set_taps(taps); + install_taps(d_new_taps); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + for(unsigned i = 0; i < interpolation(); i++) { + delete d_firs[i]; + } + } + + void + @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps) + { + d_new_taps = taps; + d_updated = true; + + // round up length to a multiple of the interpolation factor + int n = taps.size() % interpolation(); + if(n > 0) { + n = interpolation() - n; + while(n-- > 0) { + d_new_taps.insert(d_new_taps.begin(), 0); + } + } + + if(d_new_taps.size() % interpolation() != 0) { + throw std::runtime_error("@IMPL_NAME@: error setting interpolator taps.\n"); + } + } + + void + @IMPL_NAME@::install_taps(const std::vector<@TAP_TYPE@> &taps) + { + unsigned nfilters = interpolation(); + int nt = taps.size() / nfilters; + + std::vector< std::vector <@TAP_TYPE@> > xtaps(nfilters); + + for(unsigned n = 0; n < nfilters; n++) { + xtaps[n].resize (nt); + } + + for(size_t i = 0; i < taps.size(); i++) { + xtaps[i % nfilters][i / nfilters] = taps[i]; + } + + for(unsigned n = 0; n < nfilters; n++) { + d_firs[n]->set_taps (xtaps[n]); + } + + set_history(nt); + d_updated = false; + } + + std::vector<@TAP_TYPE@> + @IMPL_NAME@::taps() const + { + return d_new_taps; + } + + int + @NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const @I_TYPE@ *in = (const @I_TYPE@ *)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *)output_items[0]; + + if(d_updated) { + install_taps(d_new_taps); + return 0; // history requirements may have changed. + } + + int nfilters = interpolation(); + int ni = noutput_items / interpolation(); + + for(int i = 0; i < ni; i++) { + for(int nf = 0; nf < nfilters; nf++) { + out[nf] = d_firs[nf]->filter(&in[i]); + } + out += nfilters; + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/interp_fir_filter_XXX_impl.h.t b/gr-filter/lib/interp_fir_filter_XXX_impl.h.t new file mode 100644 index 0000000000..e505fca698 --- /dev/null +++ b/gr-filter/lib/interp_fir_filter_XXX_impl.h.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/api.h> +#include <filter/fir_filter.h> +#include <filter/@BASE_NAME@.h> +#include <vector> + +namespace gr { + namespace filter { + + class FILTER_API @IMPL_NAME@ : public @BASE_NAME@ + { + private: + bool d_updated; + std::vector<kernel::@FIR_TYPE@ *> d_firs; + std::vector<@TAP_TYPE@> d_new_taps; + + void install_taps(const std::vector<@TAP_TYPE@> &taps); + + public: + @IMPL_NAME@(unsigned interpolation, + const std::vector<@TAP_TYPE@> &taps); + + ~@IMPL_NAME@(); + + void set_taps(const std::vector<@TAP_TYPE@> &taps); + std::vector<@TAP_TYPE@> taps() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/lib/mmse_fir_interpolator_cc.cc b/gr-filter/lib/mmse_fir_interpolator_cc.cc new file mode 100644 index 0000000000..8af1fb39a6 --- /dev/null +++ b/gr-filter/lib/mmse_fir_interpolator_cc.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <filter/mmse_fir_interpolator_cc.h> +#include <filter/interpolator_taps.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + mmse_fir_interpolator_cc::mmse_fir_interpolator_cc() + { + filters.resize (NSTEPS + 1); + + for(int i = 0; i < NSTEPS + 1; i++) { + std::vector<float> t (&taps[i][0], &taps[i][NTAPS]); + filters[i] = new kernel::fir_filter_ccf(1, t); + } + } + + mmse_fir_interpolator_cc::~mmse_fir_interpolator_cc() + { + for(int i = 0; i < NSTEPS + 1; i++) + delete filters[i]; + } + + unsigned + mmse_fir_interpolator_cc::ntaps() const + { + return NTAPS; + } + + unsigned + mmse_fir_interpolator_cc::nsteps() const + { + return NSTEPS; + } + + gr_complex + mmse_fir_interpolator_cc::interpolate(const gr_complex input[], + float mu) const + { + int imu = (int)rint(mu * NSTEPS); + + if((imu < 0) || (imu > NSTEPS)) { + throw std::runtime_error("mmse_fir_interpolator_cc: imu out of bounds.\n"); + } + + gr_complex r = filters[imu]->filter(input); + return r; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/mmse_fir_interpolator_ff.cc b/gr-filter/lib/mmse_fir_interpolator_ff.cc new file mode 100644 index 0000000000..ff2c4dd873 --- /dev/null +++ b/gr-filter/lib/mmse_fir_interpolator_ff.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <filter/mmse_fir_interpolator_ff.h> +#include <filter/interpolator_taps.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + mmse_fir_interpolator_ff::mmse_fir_interpolator_ff() + { + filters.resize(NSTEPS + 1); + + for(int i = 0; i < NSTEPS + 1; i++) { + std::vector<float> t(&taps[i][0], &taps[i][NTAPS]); + filters[i] = new kernel::fir_filter_fff(1, t); + } + } + + mmse_fir_interpolator_ff::~mmse_fir_interpolator_ff() + { + for(int i = 0; i < NSTEPS + 1; i++) + delete filters[i]; + } + + unsigned + mmse_fir_interpolator_ff::ntaps() const + { + return NTAPS; + } + + unsigned + mmse_fir_interpolator_ff::nsteps() const + { + return NSTEPS; + } + + float + mmse_fir_interpolator_ff::interpolate(const float input[], + float mu) const + { + int imu = (int)rint(mu * NSTEPS); + + if((imu < 0) || (imu > NSTEPS)) { + throw std::runtime_error("mmse_fir_interpolator_ff: imu out of bounds.\n"); + } + + float r = filters[imu]->filter(input); + return r; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc b/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc new file mode 100644 index 0000000000..5480366de2 --- /dev/null +++ b/gr-filter/lib/pfb_arb_resampler_ccf_impl.cc @@ -0,0 +1,258 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pfb_arb_resampler_ccf_impl.h" +#include <gr_io_signature.h> +#include <cstdio> + +namespace gr { + namespace filter { + + pfb_arb_resampler_ccf::sptr + pfb_arb_resampler_ccf::make(float rate, + const std::vector<float> &taps, + unsigned int filter_size) + { + return gnuradio::get_initial_sptr + (new pfb_arb_resampler_ccf_impl(rate, taps, filter_size)); + } + + + pfb_arb_resampler_ccf_impl::pfb_arb_resampler_ccf_impl(float rate, + const std::vector<float> &taps, + unsigned int filter_size) + : gr_block("pfb_arb_resampler_ccf", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))), + d_updated (false) + { + d_acc = 0; // start accumulator at 0 + + /* The number of filters is specified by the user as the filter + size; this is also the interpolation rate of the filter. We + use it and the rate provided to determine the decimation + rate. This acts as a rational resampler. The flt_rate is + calculated as the residual between the integer decimation + rate and the real decimation rate and will be used to + determine to interpolation point of the resampling process. + */ + d_int_rate = filter_size; + set_rate(rate); + + // Store the last filter between calls to work + d_last_filter = 0; + + d_start_index = 0; + + d_filters = std::vector<kernel::fir_filter_ccf*>(d_int_rate); + d_diff_filters = std::vector<kernel::fir_filter_ccf*>(d_int_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_int_rate); + for(unsigned int i = 0; i < d_int_rate; i++) { + d_filters[i] = new kernel::fir_filter_ccf(1, vtaps); + d_diff_filters[i] = new kernel::fir_filter_ccf(1, vtaps); + } + + // Now, actually set the filters' taps + set_taps(taps); + d_updated = false; + } + + pfb_arb_resampler_ccf_impl::~pfb_arb_resampler_ccf_impl() + { + for(unsigned int i = 0; i < d_int_rate; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } + } + + void + pfb_arb_resampler_ccf_impl::create_taps(const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<kernel::fir_filter_ccf*> &ourfilter) + { + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_int_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(unsigned int i = 0; i < d_int_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(unsigned int j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]); + } + } + + void + pfb_arb_resampler_ccf_impl::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) + { + // Calculate the differential taps (derivative filter) by taking the difference + // between two taps. Duplicate the last one to make both filters the same length. + float tap; + difftaps.clear(); + for(unsigned int i = 0; i < newtaps.size()-1; i++) { + tap = newtaps[i+1] - newtaps[i]; + difftaps.push_back(tap); + } + difftaps.push_back(tap); + } + + void + pfb_arb_resampler_ccf_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + create_taps(taps, d_taps, d_filters); + create_taps(dtaps, d_dtaps, d_diff_filters); + set_history(d_taps_per_filter + 1); + d_updated = true; + } + + std::vector<std::vector<float> > + pfb_arb_resampler_ccf_impl::taps() const + { + return d_taps; + } + + void + pfb_arb_resampler_ccf_impl::print_taps() + { + unsigned int i, j; + for(i = 0; i < d_int_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n"); + } + } + + void + pfb_arb_resampler_ccf_impl::set_rate(float rate) + { + gruel::scoped_lock guard(d_mutex); + + d_dec_rate = (unsigned int)floor(d_int_rate/rate); + d_flt_rate = (d_int_rate/rate) - d_dec_rate; + set_relative_rate(rate); + } + + void + pfb_arb_resampler_ccf_impl::set_phase(float ph) + { + gruel::scoped_lock guard(d_mutex); + if((ph < 0) || (ph >= 2.0*M_PI)) { + throw std::runtime_error("pfb_arb_resampler_ccf: set_phase value out of bounds [0, 2pi).\n"); + } + + float ph_diff = 2.0*M_PI / (float)d_filters.size(); + d_last_filter = static_cast<int>(ph / ph_diff); + } + + float + pfb_arb_resampler_ccf_impl::phase() const + { + float ph_diff = 2.0*M_PI / static_cast<float>(d_filters.size()); + return d_last_filter * ph_diff; + } + + int + pfb_arb_resampler_ccf_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gruel::scoped_lock guard(d_mutex); + + gr_complex *in = (gr_complex*)input_items[0]; + gr_complex *out = (gr_complex*)output_items[0]; + + if(d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = d_start_index; + unsigned int j; + gr_complex o0, o1; + + // Restore the last filter position + j = d_last_filter; + + // produce output as long as we can and there are enough input samples + int max_input = ninput_items[0] - (int)d_taps_per_filter; + while((i < noutput_items) && (count < max_input)) { + // start j by wrapping around mod the number of channels + while((j < d_int_rate) && (i < noutput_items)) { + // Take the current filter and derivative filter output + o0 = d_filters[j]->filter(&in[count]); + o1 = d_diff_filters[j]->filter(&in[count]); + + out[i] = o0 + o1*d_acc; // linearly interpolate between samples + i++; + + // Adjust accumulator and index into filterbank + d_acc += d_flt_rate; + j += d_dec_rate + (int)floor(d_acc); + d_acc = fmodf(d_acc, 1.0); + } + if(i < noutput_items) { // keep state for next entry + float ss = (int)(j / d_int_rate); // number of items to skip ahead by + count += ss; // we have fully consumed another input + j = j % d_int_rate; // roll filter around + } + } + + // Store the current filter position and start of next sample + d_last_filter = j; + d_start_index = std::max(0, count - ninput_items[0]); + + // consume all we've processed but no more than we can + consume_each(std::min(count, ninput_items[0])); + return i; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_arb_resampler_ccf_impl.h b/gr-filter/lib/pfb_arb_resampler_ccf_impl.h new file mode 100644 index 0000000000..891e601e09 --- /dev/null +++ b/gr-filter/lib/pfb_arb_resampler_ccf_impl.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H +#define INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H + +#include <filter/pfb_arb_resampler_ccf.h> +#include <filter/fir_filter.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + class FILTER_API pfb_arb_resampler_ccf_impl : public pfb_arb_resampler_ccf + { + private: + std::vector<kernel::fir_filter_ccf*> d_filters; + std::vector<kernel::fir_filter_ccf*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + unsigned int d_int_rate; // the number of filters (interpolation rate) + unsigned int d_dec_rate; // the stride through the filters (decimation rate) + float d_flt_rate; // residual rate for the linear interpolation + float d_acc; + unsigned int d_last_filter; + int d_start_index; + unsigned int d_taps_per_filter; + bool d_updated; + gruel::mutex d_mutex; // mutex to protect set/work access + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param newtaps (vector of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. + * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. + */ + void create_taps(const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<kernel::fir_filter_ccf*> &ourfilter); + + public: + pfb_arb_resampler_ccf_impl(float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + ~pfb_arb_resampler_ccf_impl(); + + void set_taps(const std::vector<float> &taps); + std::vector<std::vector<float> > taps() const; + void print_taps(); + void set_rate(float rate); + + void set_phase(float ph); + float phase() const; + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_ARB_RESAMPLER_CCF_IMPL_H */ diff --git a/gr-filter/lib/pfb_arb_resampler_fff_impl.cc b/gr-filter/lib/pfb_arb_resampler_fff_impl.cc new file mode 100644 index 0000000000..6aff374fdd --- /dev/null +++ b/gr-filter/lib/pfb_arb_resampler_fff_impl.cc @@ -0,0 +1,258 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pfb_arb_resampler_fff_impl.h" +#include <gr_io_signature.h> +#include <cstdio> + +namespace gr { + namespace filter { + + pfb_arb_resampler_fff::sptr + pfb_arb_resampler_fff::make(float rate, + const std::vector<float> &taps, + unsigned int filter_size) + { + return gnuradio::get_initial_sptr + (new pfb_arb_resampler_fff_impl(rate, taps, filter_size)); + } + + + pfb_arb_resampler_fff_impl::pfb_arb_resampler_fff_impl(float rate, + const std::vector<float> &taps, + unsigned int filter_size) + : gr_block("pfb_arb_resampler_fff", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_updated(false) + { + d_acc = 0; // start accumulator at 0 + + /* The number of filters is specified by the user as the filter + size; this is also the interpolation rate of the filter. We + use it and the rate provided to determine the decimation + rate. This acts as a rational resampler. The flt_rate is + calculated as the residual between the integer decimation + rate and the real decimation rate and will be used to + determine to interpolation point of the resampling process. + */ + d_int_rate = filter_size; + set_rate(rate); + + // Store the last filter between calls to work + d_last_filter = 0; + + d_start_index = 0; + + d_filters = std::vector<kernel::fir_filter_fff*>(d_int_rate); + d_diff_filters = std::vector<kernel::fir_filter_fff*>(d_int_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_int_rate); + for(unsigned int i = 0; i < d_int_rate; i++) { + d_filters[i] = new kernel::fir_filter_fff(1, vtaps); + d_diff_filters[i] = new kernel::fir_filter_fff(1, vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + create_taps(taps, d_taps, d_filters); + create_taps(dtaps, d_dtaps, d_diff_filters); + } + + pfb_arb_resampler_fff_impl::~pfb_arb_resampler_fff_impl() + { + for(unsigned int i = 0; i < d_int_rate; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } + } + + void + pfb_arb_resampler_fff_impl::create_taps(const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<kernel::fir_filter_fff*> &ourfilter) + { + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_int_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(unsigned int i = 0; i < d_int_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(unsigned int j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]); + } + + // Set the history to ensure enough input items for each filter + set_history(d_taps_per_filter + 1); + + d_updated = true; + } + + void + pfb_arb_resampler_fff_impl::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) + { + // Calculate the differential taps (derivative filter) by taking the difference + // between two taps. Duplicate the last one to make both filters the same length. + float tap; + difftaps.clear(); + for(unsigned int i = 0; i < newtaps.size()-1; i++) { + tap = newtaps[i+1] - newtaps[i]; + difftaps.push_back(tap); + } + difftaps.push_back(tap); + } + + void + pfb_arb_resampler_fff_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + } + + std::vector<std::vector<float> > + pfb_arb_resampler_fff_impl::taps() const + { + return d_taps; + } + + void + pfb_arb_resampler_fff_impl::print_taps() + { + unsigned int i, j; + for(i = 0; i < d_int_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n"); + } + } + + void + pfb_arb_resampler_fff_impl::set_rate(float rate) + { + gruel::scoped_lock guard(d_mutex); + + d_dec_rate = (unsigned int)floor(d_int_rate/rate); + d_flt_rate = (d_int_rate/rate) - d_dec_rate; + set_relative_rate(rate); + } + + void + pfb_arb_resampler_fff_impl::set_phase(float ph) + { + gruel::scoped_lock guard(d_mutex); + if((ph < 0) || (ph >= 2.0*M_PI)) { + throw std::runtime_error("pfb_arb_resampler_ccf: set_phase value out of bounds [0, 2pi).\n"); + } + + float ph_diff = 2.0*M_PI / (float)d_filters.size(); + d_last_filter = static_cast<int>(ph / ph_diff); + } + + float + pfb_arb_resampler_fff_impl::phase() const + { + float ph_diff = 2.0*M_PI / static_cast<float>(d_filters.size()); + return d_last_filter * ph_diff; + } + + int + pfb_arb_resampler_fff_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gruel::scoped_lock guard(d_mutex); + + float *in = (float*)input_items[0]; + float *out = (float*)output_items[0]; + + if(d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = d_start_index; + unsigned int j; + float o0, o1; + + // Restore the last filter position + j = d_last_filter; + + // produce output as long as we can and there are enough input samples + int max_input = ninput_items[0] - (int)d_taps_per_filter; + while((i < noutput_items) && (count < max_input)) { + // start j by wrapping around mod the number of channels + while((j < d_int_rate) && (i < noutput_items)) { + // Take the current filter and derivative filter output + o0 = d_filters[j]->filter(&in[count]); + o1 = d_diff_filters[j]->filter(&in[count]); + + out[i] = o0 + o1*d_acc; // linearly interpolate between samples + i++; + + // Adjust accumulator and index into filterbank + d_acc += d_flt_rate; + j += d_dec_rate + (int)floor(d_acc); + d_acc = fmodf(d_acc, 1.0); + } + if(i < noutput_items) { // keep state for next entry + float ss = (int)(j / d_int_rate); // number of items to skip ahead by + count += ss; // we have fully consumed another input + j = j % d_int_rate; // roll filter around + } + } + + // Store the current filter position and start of next sample + d_last_filter = j; + d_start_index = std::max(0, count - ninput_items[0]); + + // consume all we've processed but no more than we can + consume_each(std::min(count, ninput_items[0])); + return i; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_arb_resampler_fff_impl.h b/gr-filter/lib/pfb_arb_resampler_fff_impl.h new file mode 100644 index 0000000000..5889627114 --- /dev/null +++ b/gr-filter/lib/pfb_arb_resampler_fff_impl.h @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H +#define INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H + +#include <filter/pfb_arb_resampler_fff.h> +#include <filter/fir_filter.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + class FILTER_API pfb_arb_resampler_fff_impl : public pfb_arb_resampler_fff + { + private: + std::vector<kernel::fir_filter_fff*> d_filters; + std::vector<kernel::fir_filter_fff*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + unsigned int d_int_rate; // the number of filters (interpolation rate) + unsigned int d_dec_rate; // the stride through the filters (decimation rate) + float d_flt_rate; // residual rate for the linear interpolation + float d_acc; + unsigned int d_last_filter; + int d_start_index; + unsigned int d_taps_per_filter; + bool d_updated; + gruel::mutex d_mutex; // mutex to protect set/work access + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param newtaps (vector of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. + * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. + */ + void create_taps(const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<kernel::fir_filter_fff*> &ourfilter); + public: + pfb_arb_resampler_fff_impl(float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + ~pfb_arb_resampler_fff_impl(); + + void set_taps(const std::vector<float> &taps); + std::vector<std::vector<float> > taps() const; + void print_taps(); + void set_rate(float rate); + + void set_phase(float ph); + float phase() const; + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_ARB_RESAMPLER_FFF_IMPL_H */ diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.cc b/gr-filter/lib/pfb_channelizer_ccf_impl.cc new file mode 100644 index 0000000000..ca92066f51 --- /dev/null +++ b/gr-filter/lib/pfb_channelizer_ccf_impl.cc @@ -0,0 +1,192 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pfb_channelizer_ccf_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + pfb_channelizer_ccf::sptr pfb_channelizer_ccf::make(unsigned int nfilts, + const std::vector<float> &taps, + float oversample_rate) + { + return gnuradio::get_initial_sptr(new pfb_channelizer_ccf_impl(nfilts, taps, + oversample_rate)); + } + + pfb_channelizer_ccf_impl::pfb_channelizer_ccf_impl(unsigned int nfilts, + const std::vector<float> &taps, + float oversample_rate) + : gr_block("pfb_channelizer_ccf", + gr_make_io_signature(nfilts, nfilts, sizeof(gr_complex)), + gr_make_io_signature(1, nfilts, sizeof(gr_complex))), + polyphase_filterbank(nfilts, taps), + d_updated(false), d_oversample_rate(oversample_rate) + { + // The over sampling rate must be rationally related to the number of channels + // in that it must be N/i for i in [1,N], which gives an outputsample rate + // of [fs/N, fs] where fs is the input sample rate. + // This tests the specified input sample rate to see if it conforms to this + // requirement within a few significant figures. + double intp = 0; + double fltp = modf(nfilts / oversample_rate, &intp); + if(fltp != 0.0) + throw std::invalid_argument("pfb_channelizer: oversample rate must be N/i for i in [1, N]"); + + set_relative_rate(1.0/intp); + + // Default channel map + d_channel_map.resize(d_nfilts); + for(unsigned int i = 0; i < d_nfilts; i++) { + d_channel_map[i] = i; + } + + // Although the filters change, we use this look up table + // to set the index of the FFT input buffer, which equivalently + // performs the FFT shift operation on every other turn. + d_rate_ratio = (int)rintf(d_nfilts / d_oversample_rate); + d_idxlut = new int[d_nfilts]; + for(unsigned int i = 0; i < d_nfilts; i++) { + d_idxlut[i] = d_nfilts - ((i + d_rate_ratio) % d_nfilts) - 1; + } + + // Calculate the number of filtering rounds to do to evenly + // align the input vectors with the output channels + d_output_multiple = 1; + while((d_output_multiple * d_rate_ratio) % d_nfilts != 0) + d_output_multiple++; + set_output_multiple(d_output_multiple); + + set_history(d_taps_per_filter+1); + } + + pfb_channelizer_ccf_impl::~pfb_channelizer_ccf_impl() + { + delete [] d_idxlut; + } + + void + pfb_channelizer_ccf_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + + polyphase_filterbank::set_taps(taps); + set_history(d_taps_per_filter+1); + d_updated = true; + } + + void + pfb_channelizer_ccf_impl::print_taps() + { + polyphase_filterbank::print_taps(); + } + + std::vector<std::vector<float> > + pfb_channelizer_ccf_impl::taps() const + { + return polyphase_filterbank::taps(); + } + + void + pfb_channelizer_ccf_impl::set_channel_map(const std::vector<int> &map) + { + gruel::scoped_lock guard(d_mutex); + + if(map.size() > 0) { + unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end()); + unsigned int min = (unsigned int)*std::min_element(map.begin(), map.end()); + if((max >= d_nfilts) || (min < 0)) { + throw std::invalid_argument("pfb_channelizer_ccf_impl::set_channel_map: map range out of bounds.\n"); + } + d_channel_map = map; + } + } + + std::vector<int> + pfb_channelizer_ccf_impl::channel_map() const + { + return d_channel_map; + } + + int + pfb_channelizer_ccf_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gruel::scoped_lock guard(d_mutex); + + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if(d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + size_t noutputs = output_items.size(); + + int n=1, i=-1, j=0, oo=0, last; + int toconsume = (int)rintf(noutput_items/d_oversample_rate); + while(n <= toconsume) { + j = 0; + i = (i + d_rate_ratio) % d_nfilts; + last = i; + while(i >= 0) { + in = (gr_complex*)input_items[j]; + d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n]); + j++; + i--; + } + + i = d_nfilts-1; + while(i > last) { + in = (gr_complex*)input_items[j]; + d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n-1]); + j++; + i--; + } + + n += (i+d_rate_ratio) >= (int)d_nfilts; + + // despin through FFT + d_fft->execute(); + + // Send to output channels + for(unsigned int nn = 0; nn < noutputs; nn++) { + out = (gr_complex*)output_items[nn]; + out[oo] = d_fft->get_outbuf()[d_channel_map[nn]]; + } + oo++; + } + + consume_each(toconsume); + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_channelizer_ccf_impl.h b/gr-filter/lib/pfb_channelizer_ccf_impl.h new file mode 100644 index 0000000000..16b112b9a0 --- /dev/null +++ b/gr-filter/lib/pfb_channelizer_ccf_impl.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_FILTER_PFB_CHANNELIZER_CCF_IMPL_H +#define INCLUDED_FILTER_PFB_CHANNELIZER_CCF_IMPL_H + +#include <filter/pfb_channelizer_ccf.h> +#include <filter/polyphase_filterbank.h> +#include <filter/fir_filter.h> +#include <fft/fft.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + class FILTER_API pfb_channelizer_ccf_impl : public pfb_channelizer_ccf, kernel::polyphase_filterbank + { + private: + bool d_updated; + float d_oversample_rate; + int *d_idxlut; + int d_rate_ratio; + int d_output_multiple; + std::vector<int> d_channel_map; + gruel::mutex d_mutex; // mutex to protect set/work access + + public: + pfb_channelizer_ccf_impl(unsigned int nfilts, + const std::vector<float> &taps, + float oversample_rate); + + ~pfb_channelizer_ccf_impl(); + + void set_taps(const std::vector<float> &taps); + void print_taps(); + std::vector<std::vector<float> > taps() const; + + void set_channel_map(const std::vector<int> &map); + std::vector<int> channel_map() const; + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.cc b/gr-filter/lib/pfb_decimator_ccf_impl.cc new file mode 100644 index 0000000000..f9a60cb28d --- /dev/null +++ b/gr-filter/lib/pfb_decimator_ccf_impl.cc @@ -0,0 +1,137 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pfb_decimator_ccf_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + pfb_decimator_ccf::sptr + pfb_decimator_ccf::make(unsigned int decim, + const std::vector<float> &taps, + unsigned int channel) + { + return gnuradio::get_initial_sptr + (new pfb_decimator_ccf_impl(decim, taps, channel)); + } + + + pfb_decimator_ccf_impl::pfb_decimator_ccf_impl(unsigned int decim, + const std::vector<float> &taps, + unsigned int channel) + : gr_sync_block("pfb_decimator_ccf", + gr_make_io_signature(decim, decim, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))), + polyphase_filterbank(decim, taps), + d_updated(false), d_chan(channel) + { + d_rate = decim; + d_rotator = new gr_complex[d_rate]; + + set_relative_rate(1.0/(float)decim); + set_history(d_taps_per_filter+1); + } + + pfb_decimator_ccf_impl::~pfb_decimator_ccf_impl() + { + } + + void + pfb_decimator_ccf_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + + polyphase_filterbank::set_taps(taps); + set_history(d_taps_per_filter+1); + d_updated = true; + } + + void + pfb_decimator_ccf_impl::print_taps() + { + polyphase_filterbank::print_taps(); + } + + std::vector<std::vector<float> > + pfb_decimator_ccf_impl::taps() const + { + return polyphase_filterbank::taps(); + } + +#define ROTATEFFT + + int + pfb_decimator_ccf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gruel::scoped_lock guard(d_mutex); + + gr_complex *in; + gr_complex *out = (gr_complex *)output_items[0]; + + if(d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i; + for(i = 0; i < noutput_items; i++) { + // Move through filters from bottom to top + out[i] = 0; + for(int j = d_rate-1; j >= 0; j--) { + // Take in the items from the first input stream to d_rate + in = (gr_complex*)input_items[d_rate - 1 - j]; + + // Filter current input stream from bottom filter to top + // The rotate them by expj(j*k*2pi/M) where M is the number of filters + // (the decimation rate) and k is the channel number to extract + + // This is the real math that goes on; we abuse the FFT to do this quickly + // for decimation rates > N where N is a small number (~5): + // out[i] += d_filters[j]->filter(&in[i])*gr_expj(j*d_chan*2*M_PI/d_rate); +#ifdef ROTATEFFT + d_fft->get_inbuf()[j] = d_filters[j]->filter(&in[i]); +#else + out[i] += d_filters[j]->filter(&in[i])*d_rotator[i]; +#endif + } + +#ifdef ROTATEFFT + // Perform the FFT to do the complex multiply despinning for all channels + d_fft->execute(); + + // Select only the desired channel out + out[i] = d_fft->get_outbuf()[d_chan]; +#endif + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_decimator_ccf_impl.h b/gr-filter/lib/pfb_decimator_ccf_impl.h new file mode 100644 index 0000000000..c4338a5eca --- /dev/null +++ b/gr-filter/lib/pfb_decimator_ccf_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_DECIMATOR_CCF_IMPL_H +#define INCLUDED_PFB_DECIMATOR_CCF_IMPL_H + +#include <filter/pfb_decimator_ccf.h> +#include <filter/polyphase_filterbank.h> +#include <filter/fir_filter.h> +#include <fft/fft.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + class FILTER_API pfb_decimator_ccf_impl : public pfb_decimator_ccf, kernel::polyphase_filterbank + { + private: + bool d_updated; + unsigned int d_rate; + unsigned int d_chan; + gr_complex *d_rotator; + gruel::mutex d_mutex; // mutex to protect set/work access + + public: + pfb_decimator_ccf_impl(unsigned int decim, + const std::vector<float> &taps, + unsigned int channel); + + ~pfb_decimator_ccf_impl(); + + void set_taps(const std::vector<float> &taps); + void print_taps(); + std::vector<std::vector<float> > taps() const; + //void set_channel(unsigned int channel); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_DECIMATOR_CCF_IMPL_H */ diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.cc b/gr-filter/lib/pfb_interpolator_ccf_impl.cc new file mode 100644 index 0000000000..572db728b3 --- /dev/null +++ b/gr-filter/lib/pfb_interpolator_ccf_impl.cc @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pfb_interpolator_ccf_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + pfb_interpolator_ccf::sptr + pfb_interpolator_ccf::make(unsigned int interp, + const std::vector<float> &taps) + { + return gnuradio::get_initial_sptr + (new pfb_interpolator_ccf_impl(interp, taps)); + } + + + pfb_interpolator_ccf_impl::pfb_interpolator_ccf_impl(unsigned int interp, + const std::vector<float> &taps) + : gr_sync_interpolator("pfb_interpolator_ccf", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex)), + interp), + polyphase_filterbank(interp, taps), + d_updated (false), d_rate(interp) + { + set_history(d_taps_per_filter+1); + } + + pfb_interpolator_ccf_impl::~pfb_interpolator_ccf_impl() + { + } + + void + pfb_interpolator_ccf_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + + polyphase_filterbank::set_taps(taps); + set_history(d_taps_per_filter+1); + d_updated = true; + } + + void + pfb_interpolator_ccf_impl::print_taps() + { + polyphase_filterbank::print_taps(); + } + + std::vector<std::vector<float> > + pfb_interpolator_ccf_impl::taps() const + { + return polyphase_filterbank::taps(); + } + + int + pfb_interpolator_ccf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gr_complex *in = (gr_complex*)input_items[0]; + gr_complex *out = (gr_complex*)output_items[0]; + + if(d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = 0; + + while(i < noutput_items) { + for(unsigned int j = 0; j < d_rate; j++) { + out[i] = d_filters[j]->filter(&in[count]); + i++; + } + count++; + } + + return i; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_interpolator_ccf_impl.h b/gr-filter/lib/pfb_interpolator_ccf_impl.h new file mode 100644 index 0000000000..7e1fe2ca11 --- /dev/null +++ b/gr-filter/lib/pfb_interpolator_ccf_impl.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H +#define INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H + +#include <filter/pfb_interpolator_ccf.h> +#include <filter/polyphase_filterbank.h> +#include <filter/fir_filter.h> +#include <fft/fft.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + class FILTER_API pfb_interpolator_ccf_impl : public pfb_interpolator_ccf, kernel::polyphase_filterbank + { + private: + bool d_updated; + unsigned int d_rate; + gruel::mutex d_mutex; // mutex to protect set/work access + + public: + pfb_interpolator_ccf_impl(unsigned int interp, + const std::vector<float> &taps); + + ~pfb_interpolator_ccf_impl(); + + void set_taps(const std::vector<float> &taps); + void print_taps(); + std::vector<std::vector<float> > taps() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_INTERPOLATOR_CCF_IMPL_H */ diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.cc b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc new file mode 100644 index 0000000000..1e9c099c1e --- /dev/null +++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.cc @@ -0,0 +1,288 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pfb_synthesizer_ccf_impl.h" +#include <gr_io_signature.h> +#include <cstdio> + +namespace gr { + namespace filter { + + pfb_synthesizer_ccf::sptr + pfb_synthesizer_ccf::make(unsigned int numchans, + const std::vector<float> &taps, + bool twox) + { + return gnuradio::get_initial_sptr + (new pfb_synthesizer_ccf_impl(numchans, taps, twox)); + } + + + pfb_synthesizer_ccf_impl::pfb_synthesizer_ccf_impl(unsigned int numchans, + const std::vector<float> &taps, + bool twox) + : gr_sync_interpolator("pfb_synthesizer_ccf", + gr_make_io_signature(1, numchans, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex)), + numchans), + d_updated (false), d_numchans(numchans), d_state(0) + { + // set up 2x multiplier; if twox==True, set to 2, otherwise to 1 + d_twox = (twox ? 2 : 1); + if(d_numchans % d_twox != 0) { + throw std::invalid_argument("pfb_synthesizer_ccf: number of channels must be even for 2x oversampling.\n"); + } + + d_filters = std::vector<kernel::fir_filter_with_buffer_ccf*>(d_twox*d_numchans); + d_channel_map.resize(d_twox*d_numchans); + + // Create a FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_twox*d_numchans); + for(unsigned int i = 0; i < d_twox*d_numchans; i++) { + d_filters[i] = new kernel::fir_filter_with_buffer_ccf(vtaps); + d_channel_map[i] = i; + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the IFFT to handle the input channel rotations + d_fft = new fft::fft_complex(d_twox*d_numchans, false); + memset(d_fft->get_inbuf(), 0, d_twox*d_numchans*sizeof(gr_complex)); + + set_output_multiple(d_numchans); + } + + pfb_synthesizer_ccf_impl::~pfb_synthesizer_ccf_impl() + { + for(unsigned int i = 0; i < d_twox*d_numchans; i++) { + delete d_filters[i]; + } + } + + void + pfb_synthesizer_ccf_impl::set_taps(const std::vector<float> &taps) + { + gruel::scoped_lock guard(d_mutex); + + if(d_twox == 1) + set_taps1(taps); + else + set_taps2(taps); + + // Set the history to ensure enough input items for each filter + set_history(d_taps_per_filter+1); + + d_updated = true; + } + + void + pfb_synthesizer_ccf_impl::set_taps1(const std::vector<float> &taps) + { + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + } + + void + pfb_synthesizer_ccf_impl::set_taps2 (const std::vector<float> &taps) + { + unsigned int i,j; + int state = 0; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_twox*d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + d_taps[d_numchans+i] = std::vector<float>(d_taps_per_filter, 0); + state = 0; + for(j = 0; j < d_taps_per_filter; j++) { + // add taps to channels in reverse order + // Zero out every other tap + if(state == 0) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; + d_taps[d_numchans + i][j] = 0; + state = 1; + } + else { + d_taps[i][j] = 0; + d_taps[d_numchans + i][j] = tmp_taps[i + j*d_numchans]; + state = 0; + } + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + d_filters[d_numchans + i]->set_taps(d_taps[d_numchans + i]); + } + } + + void + pfb_synthesizer_ccf_impl::print_taps() + { + unsigned int i, j; + for(i = 0; i < d_twox*d_numchans; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } + } + + std::vector< std::vector<float> > + pfb_synthesizer_ccf_impl::taps() const + { + return d_taps; + } + + void + pfb_synthesizer_ccf_impl::set_channel_map(const std::vector<int> &map) + { + gruel::scoped_lock guard(d_mutex); + + if(map.size() > 0) { + unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end()); + unsigned int min = (unsigned int)*std::min_element(map.begin(), map.end()); + if((max >= d_twox*d_numchans) || (min < 0)) { + throw std::invalid_argument("gr_pfb_synthesizer_ccf::set_channel_map: map range out of bounds.\n"); + } + d_channel_map = map; + + // Zero out fft buffer so that unused channels are always 0 + memset(d_fft->get_inbuf(), 0,d_twox*d_numchans*sizeof(gr_complex)); + } + } + + std::vector<int> + pfb_synthesizer_ccf_impl::channel_map() const + { + return d_channel_map; + } + + int + pfb_synthesizer_ccf_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + gruel::scoped_lock guard(d_mutex); + + gr_complex *in = (gr_complex*)input_items[0]; + gr_complex *out = (gr_complex*)output_items[0]; + + if(d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + unsigned int n, i; + size_t ninputs = input_items.size(); + + // Algoritm for critically sampled channels + if(d_twox == 1) { + for(n = 0; n < noutput_items/d_numchans; n++) { + for(i = 0; i < ninputs; i++) { + in = (gr_complex*)input_items[i]; + d_fft->get_inbuf()[d_channel_map[i]] = in[n]; + } + + // spin through IFFT + d_fft->execute(); + + for(i = 0; i < d_numchans; i++) { + out[i] = d_filters[i]->filter(d_fft->get_outbuf()[i]); + } + out += d_numchans; + } + } + + // Algorithm for oversampling by 2x + else { + for(n = 0; n < noutput_items/d_numchans; n++) { + for(i = 0; i < ninputs; i++) { + in = (gr_complex*)input_items[i]; + d_fft->get_inbuf()[d_channel_map[i]] = in[n]; + } + + // spin through IFFT + d_fft->execute(); + + // Output is sum of two filters, but the input buffer to the filters must be circularly + // shifted by numchans every time through, done by using d_state to determine which IFFT + // buffer position to pull from. + for(i = 0; i < d_numchans; i++) { + out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]); + out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]); + } + d_state ^= 1; + + out += d_numchans; + } + } + + return noutput_items; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/pfb_synthesizer_ccf_impl.h b/gr-filter/lib/pfb_synthesizer_ccf_impl.h new file mode 100644 index 0000000000..adffc143f2 --- /dev/null +++ b/gr-filter/lib/pfb_synthesizer_ccf_impl.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifndef INCLUDED_PFB_SYNTHESIZER_CCF_IMPL_H +#define INCLUDED_PFB_SYNTHESIZER_CCF_IMPL_H + +#include <filter/pfb_synthesizer_ccf.h> +#include <filter/fir_filter_with_buffer.h> +#include <fft/fft.h> +#include <gruel/thread.h> + +namespace gr { + namespace filter { + + // While this is a polyphase_filterbank, we don't use the normal + // parent class because we have to use the fir_filter_with_buffer + // objects instead of normal filters. + + class FILTER_API pfb_synthesizer_ccf_impl : public pfb_synthesizer_ccf + { + private: + bool d_updated; + unsigned int d_numchans; + unsigned int d_taps_per_filter; + fft::fft_complex *d_fft; + std::vector< kernel::fir_filter_with_buffer_ccf*> d_filters; + std::vector< std::vector<float> > d_taps; + int d_state; + std::vector<int> d_channel_map; + unsigned int d_twox; + gruel::mutex d_mutex; // mutex to protect set/work access + + /*! + * \brief Tap setting algorithm for critically sampled channels + */ + void set_taps1(const std::vector<float> &taps); + + /*! + * \brief Tap setting algorithm for 2x over-sampled channels + */ + void set_taps2(const std::vector<float> &taps); + + + public: + pfb_synthesizer_ccf_impl(unsigned int numchans, + const std::vector<float> &taps, + bool twox); + ~pfb_synthesizer_ccf_impl(); + + void set_taps(const std::vector<float> &taps); + std::vector<std::vector<float> > taps() const; + void print_taps(); + + void set_channel_map(const std::vector<int> &map); + std::vector<int> channel_map() const; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_PFB_SYNTHESIZER_CCF_IMPL_H */ diff --git a/gr-filter/lib/pm_remez.cc b/gr-filter/lib/pm_remez.cc new file mode 100644 index 0000000000..e7136bd83a --- /dev/null +++ b/gr-filter/lib/pm_remez.cc @@ -0,0 +1,834 @@ +/************************************************************************** + * Parks-McClellan algorithm for FIR filter design (C version) + *------------------------------------------------- + * Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu) + * Copyright (c) 2004 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA + * + * + * Sep 1999 - Paul Kienzle (pkienzle@cs.indiana.edu) + * Modified for use in octave as a replacement for the matlab function + * remez.mex. In particular, magnitude responses are required for all + * band edges rather than one per band, griddensity is a parameter, + * and errors are returned rather than printed directly. + * Mar 2000 - Kai Habel (kahacjde@linux.zrz.tu-berlin.de) + * Change: ColumnVector x=arg(i).vector_value(); + * to: ColumnVector x(arg(i).vector_value()); + * There appear to be some problems with the routine search. See comments + * therein [search for PAK:]. I haven't looked closely at the rest + * of the code---it may also have some problems. + *************************************************************************/ + +/* + * This code was extracted from octave.sf.net, and wrapped with + * GNU Radio glue. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <filter/pm_remez.h> +#include <cmath> +#include <assert.h> +#include <iostream> + +#ifndef LOCAL_BUFFER +#include <vector> +#define LOCAL_BUFFER(T, buf, size) \ + std::vector<T> buf ## _vector (size); \ + T *buf = &(buf ## _vector[0]) +#endif + +namespace gr { + namespace filter { + +#define CONST const +#define BANDPASS 1 +#define DIFFERENTIATOR 2 +#define HILBERT 3 + +#define NEGATIVE 0 +#define POSITIVE 1 + +#define Pi 3.14159265358979323846 +#define Pi2 (2*Pi) + +#define GRIDDENSITY 16 +#define MAXITERATIONS 40 + + /******************* + * create_dense_grid + *================= + * + * Creates the dense grid of frequencies from the specified bands. + * Also creates the Desired Frequency Response function (D[]) and + * the Weight function (W[]) on that dense grid + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int numtaps - Number of taps in the resulting filter + * int numband - Number of bands in user specification + * double bands[] - User-specified band edges [2*numband] + * double des[] - Desired response per band [2*numband] + * double weight[] - Weight per band [numband] + * int symmetry - Symmetry of filter - used for grid check + * int griddensity + * + * OUTPUT: + * ------- + * int gridsize - Number of elements in the dense frequency grid + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + *******************/ + + static void + create_dense_grid(int r, int numtaps, int numband, const double bands[], + const double des[], const double weight[], int gridsize, + double Grid[], double D[], double W[], + int symmetry, int griddensity) + { + int i, j, k, band; + double delf, lowf, highf, grid0; + + delf = 0.5/(griddensity*r); + + /* + * For differentiator, hilbert, + * symmetry is odd and Grid[0] = max(delf, bands[0]) + */ + grid0 = (symmetry == NEGATIVE) && (delf > bands[0]) ? delf : bands[0]; + + j=0; + for(band=0; band < numband; band++) { + lowf = (band==0 ? grid0 : bands[2*band]); + highf = bands[2*band + 1]; + k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */ + for(i=0; i<k; i++) { + D[j] = des[2*band] + i*(des[2*band+1]-des[2*band])/(k-1); + W[j] = weight[band]; + Grid[j] = lowf; + lowf += delf; + j++; + } + Grid[j-1] = highf; + } + + /* + * Similar to above, if odd symmetry, last grid point can't be .5 + * - but, if there are even taps, leave the last grid point at .5 + */ + if((symmetry == NEGATIVE) && + (Grid[gridsize-1] > (0.5 - delf)) && + (numtaps % 2)) + { + Grid[gridsize-1] = 0.5-delf; + } + } + + + /******************** + * initial_guess + *============== + * Places Extremal Frequencies evenly throughout the dense grid. + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int gridsize - Number of elements in the dense frequency grid + * + * OUTPUT: + * ------- + * int ext[] - Extremal indexes to dense frequency grid [r+1] + ********************/ + + static void + initial_guess(int r, int Ext[], int gridsize) + { + int i; + + for(i=0; i<=r; i++) + Ext[i] = i * (gridsize-1) / r; + } + + + /*********************** + * calc_parms + *=========== + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + * + * OUTPUT: + * ------- + * double ad[] - 'b' in Oppenheim & Schafer [r+1] + * double x[] - [r+1] + * double y[] - 'C' in Oppenheim & Schafer [r+1] + ***********************/ + + static void + calc_parms(int r, int Ext[], double Grid[], double D[], double W[], + double ad[], double x[], double y[]) + { + int i, j, k, ld; + double sign, xi, delta, denom, numer; + + /* + * Find x[] + */ + for(i = 0; i <= r; i++) + x[i] = cos(Pi2 * Grid[Ext[i]]); + + /* + * Calculate ad[] - Oppenheim & Schafer eq 7.132 + */ + ld = (r-1)/15 + 1; /* Skips around to avoid round errors */ + for(i = 0; i <= r; i++) { + denom = 1.0; + xi = x[i]; + for(j = 0; j < ld; j++) { + for(k = j; k <= r; k += ld) + if(k != i) + denom *= 2.0*(xi - x[k]); + } + if(fabs(denom) < 0.00001) + denom = 0.00001; + ad[i] = 1.0/denom; + } + + /* + * Calculate delta - Oppenheim & Schafer eq 7.131 + */ + numer = denom = 0; + sign = 1; + for(i = 0; i <= r; i++) { + numer += ad[i] * D[Ext[i]]; + denom += sign * ad[i]/W[Ext[i]]; + sign = -sign; + } + delta = numer/denom; + sign = 1; + + /* + * Calculate y[] - Oppenheim & Schafer eq 7.133b + */ + for(i = 0; i <= r; i++) { + y[i] = D[Ext[i]] - sign * delta/W[Ext[i]]; + sign = -sign; + } + } + + + /********************* + * compute_A + *========== + * Using values calculated in calc_parms, compute_A calculates the + * actual filter response at a given frequency (freq). Uses + * eq 7.133a from Oppenheim & Schafer. + * + * + * INPUT: + * ------ + * double freq - Frequency (0 to 0.5) at which to calculate A + * int r - 1/2 the number of filter coefficients + * double ad[] - 'b' in Oppenheim & Schafer [r+1] + * double x[] - [r+1] + * double y[] - 'C' in Oppenheim & Schafer [r+1] + * + * OUTPUT: + * ------- + * Returns double value of A[freq] + *********************/ + + static double + compute_A(double freq, int r, double ad[], double x[], double y[]) + { + int i; + double xc, c, denom, numer; + + denom = numer = 0; + xc = cos(Pi2 * freq); + for(i = 0; i <= r; i++) { + c = xc - x[i]; + if(fabs(c) < 1.0e-7) { + numer = y[i]; + denom = 1; + break; + } + c = ad[i]/c; + denom += c; + numer += c*y[i]; + } + return numer/denom; + } + + + /************************ + * calc_error + *=========== + * Calculates the Error function from the desired frequency response + * on the dense grid (D[]), the weight function on the dense grid (W[]), + * and the present response calculation (A[]) + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * double ad[] - [r+1] + * double x[] - [r+1] + * double y[] - [r+1] + * int gridsize - Number of elements in the dense frequency grid + * double Grid[] - Frequencies on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the desnse grid [gridsize] + * + * OUTPUT: + * ------- + * double E[] - Error function on dense grid [gridsize] + ************************/ + + static void + calc_error(int r, double ad[], double x[], double y[], + int gridsize, double Grid[], + double D[], double W[], double E[]) + { + int i; + double A; + + for(i = 0; i < gridsize; i++) { + A = compute_A(Grid[i], r, ad, x, y); + E[i] = W[i] * (D[i] - A); + } + } + + /************************ + * search + *======== + * Searches for the maxima/minima of the error curve. If more than + * r+1 extrema are found, it uses the following heuristic (thanks + * Chris Hanson): + * 1) Adjacent non-alternating extrema deleted first. + * 2) If there are more than one excess extrema, delete the + * one with the smallest error. This will create a non-alternation + * condition that is fixed by 1). + * 3) If there is exactly one excess extremum, delete the smaller + * of the first/last extremum + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1] + * int gridsize - Number of elements in the dense frequency grid + * double E[] - Array of error values. [gridsize] + * OUTPUT: + * ------- + * int Ext[] - New indexes to extremal frequencies [r+1] + ************************/ + static int + search(int r, int Ext[], + int gridsize, double E[]) + { + int i, j, k, l, extra; /* Counters */ + int up, alt; + int *foundExt; /* Array of found extremals */ + + /* + * Allocate enough space for found extremals. + */ + foundExt = (int *)malloc((2*r) * sizeof(int)); + k = 0; + + /* + * Check for extremum at 0. + */ + if(((E[0] > 0.0) && (E[0] > E[1])) || + ((E[0] < 0.0) && (E[0] < E[1]))) + foundExt[k++] = 0; + + /* + * Check for extrema inside dense grid + */ + for(i = 1; i < gridsize-1; i++) { + if(((E[i] >= E[i-1]) && (E[i] > E[i+1]) && (E[i] > 0.0)) || + ((E[i] <= E[i-1]) && (E[i] < E[i+1]) && (E[i] < 0.0))) { + // PAK: we sometimes get too many extremal frequencies + if(k >= 2*r) + return -3; + foundExt[k++] = i; + } + } + + /* + * Check for extremum at 0.5 + */ + j = gridsize-1; + if(((E[j] > 0.0) && (E[j] > E[j-1])) || + ((E[j] < 0.0) && (E[j] < E[j-1]))) { + if(k >= 2*r) + return -3; + foundExt[k++] = j; + } + + // PAK: we sometimes get not enough extremal frequencies + if(k < r+1) + return -2; + + /* + * Remove extra extremals + */ + extra = k - (r+1); + assert(extra >= 0); + + while(extra > 0) { + if(E[foundExt[0]] > 0.0) + up = 1; /* first one is a maxima */ + else + up = 0; /* first one is a minima */ + + l=0; + alt = 1; + for(j = 1; j < k; j++) { + if(fabs(E[foundExt[j]]) < fabs(E[foundExt[l]])) + l = j; /* new smallest error. */ + if((up) && (E[foundExt[j]] < 0.0)) + up = 0; /* switch to a minima */ + else if((!up) && (E[foundExt[j]] > 0.0)) + up = 1; /* switch to a maxima */ + else { + alt = 0; + // PAK: break now and you will delete the smallest overall + // extremal. If you want to delete the smallest of the + // pair of non-alternating extremals, then you must do: + // + // if(fabs(E[foundExt[j]]) < fabs(E[foundExt[j-1]])) l=j; + // else l=j-1; + break; /* Ooops, found two non-alternating */ + } /* extrema. Delete smallest of them */ + } /* if the loop finishes, all extrema are alternating */ + + /* + * If there's only one extremal and all are alternating, + * delete the smallest of the first/last extremals. + */ + if((alt) && (extra == 1)) { + if(fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]])) + /* Delete last extremal */ + l = k-1; + // PAK: changed from l = foundExt[k-1]; + else + /* Delete first extremal */ + l = 0; + // PAK: changed from l = foundExt[0]; + } + + for(j = l; j < k-1; j++) { /* Loop that does the deletion */ + foundExt[j] = foundExt[j+1]; + assert(foundExt[j]<gridsize); + } + k--; + extra--; + } + + for(i = 0; i <= r; i++) { + assert(foundExt[i]<gridsize); + Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */ + } + + free(foundExt); + return 0; + } + + + /********************* + * freq_sample + *============ + * Simple frequency sampling algorithm to determine the impulse + * response h[] from A's found in compute_A + * + * + * INPUT: + * ------ + * int N - Number of filter coefficients + * double A[] - Sample points of desired response [N/2] + * int symmetry - Symmetry of desired filter + * + * OUTPUT: + * ------- + * double h[] - Impulse Response of final filter [N] + *********************/ + static void + freq_sample(int N, double A[], double h[], int symm) + { + int n, k; + double x, val, M; + + M = (N-1.0)/2.0; + if(symm == POSITIVE) { + if(N % 2) { + for(n = 0; n < N; n++) { + val = A[0]; + x = Pi2 * (n - M)/N; + for(k=1; k<=M; k++) + val += 2.0 * A[k] * cos(x*k); + h[n] = val/N; + } + } + else { + for(n = 0; n < N; n++) { + val = A[0]; + x = Pi2 * (n - M)/N; + for(k = 1; k <= (N/2-1); k++) + val += 2.0 * A[k] * cos(x*k); + h[n] = val/N; + } + } + } + else { + if(N % 2) { + for(n = 0; n < N; n++) { + val = 0; + x = Pi2 * (n - M)/N; + for(k = 1; k <= M; k++) + val += 2.0 * A[k] * sin(x*k); + h[n] = val/N; + } + } + else { + for(n = 0; n < N; n++) { + val = A[N/2] * sin(Pi * (n - M)); + x = Pi2 * (n - M)/N; + for(k = 1; k <= (N/2-1); k++) + val += 2.0 * A[k] * sin(x*k); + h[n] = val/N; + } + } + } + } + + /******************* + * is_done + *======== + * Checks to see if the error function is small enough to consider + * the result to have converged. + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coeffiecients + * int Ext[] - Indexes to extremal frequencies [r+1] + * double E[] - Error function on the dense grid [gridsize] + * + * OUTPUT: + * ------- + * Returns 1 if the result converged + * Returns 0 if the result has not converged + ********************/ + + static bool + is_done(int r, int Ext[], double E[]) + { + int i; + double min, max, current; + + min = max = fabs(E[Ext[0]]); + for(i = 1; i <= r; i++) { + current = fabs(E[Ext[i]]); + if(current < min) + min = current; + if(current > max) + max = current; + } + return(((max-min)/max) < 0.0001); + } + + /******************** + * remez + *======= + * Calculates the optimal (in the Chebyshev/minimax sense) + * FIR filter impulse response given a set of band edges, + * the desired reponse on those bands, and the weight given to + * the error in those bands. + * + * INPUT: + * ------ + * int numtaps - Number of filter coefficients + * int numband - Number of bands in filter specification + * double bands[] - User-specified band edges [2 * numband] + * double des[] - User-specified band responses [2 * numband] + * double weight[] - User-specified error weights [numband] + * int type - Type of filter + * + * OUTPUT: + * ------- + * double h[] - Impulse response of final filter [numtaps] + * returns - true on success, false on failure to converge + ********************/ + + static int + remez(double h[], int numtaps, + int numband, const double bands[], + const double des[], const double weight[], + int type, int griddensity) + { + double *Grid, *W, *D, *E; + int i, iter, gridsize, r, *Ext; + double *taps, c; + double *x, *y, *ad; + int symmetry; + + if(type == BANDPASS) + symmetry = POSITIVE; + else + symmetry = NEGATIVE; + + r = numtaps/2; /* number of extrema */ + if((numtaps % 2) && (symmetry == POSITIVE)) + r++; + + /* + * Predict dense grid size in advance for memory allocation + * .5 is so we round up, not truncate + */ + gridsize = 0; + for(i = 0; i < numband; i++) { + gridsize +=(int)(2*r*griddensity*(bands[2*i+1] - bands[2*i]) + .5); + } + if(symmetry == NEGATIVE) { + gridsize--; + } + + /* + * Dynamically allocate memory for arrays with proper sizes + */ + Grid = (double *)malloc(gridsize * sizeof(double)); + D = (double *)malloc(gridsize * sizeof(double)); + W = (double *)malloc(gridsize * sizeof(double)); + E = (double *)malloc(gridsize * sizeof(double)); + Ext = (int *)malloc((r+1) * sizeof(int)); + taps = (double *)malloc((r+1) * sizeof(double)); + x = (double *)malloc((r+1) * sizeof(double)); + y = (double *)malloc((r+1) * sizeof(double)); + ad = (double *)malloc((r+1) * sizeof(double)); + + /* + * Create dense frequency grid + */ + create_dense_grid(r, numtaps, numband, bands, des, weight, + gridsize, Grid, D, W, symmetry, griddensity); + initial_guess(r, Ext, gridsize); + + /* + * For Differentiator: (fix grid) + */ + if(type == DIFFERENTIATOR) { + for(i = 0; i < gridsize; i++) { + /* D[i] = D[i]*Grid[i]; */ + if(D[i] > 0.0001) + W[i] = W[i]/Grid[i]; + } + } + + /* + * For odd or Negative symmetry filters, alter the + * D[] and W[] according to Parks McClellan + */ + if(symmetry == POSITIVE) { + if(numtaps % 2 == 0) { + for(i = 0; i < gridsize; i++) { + c = cos(Pi * Grid[i]); + D[i] /= c; + W[i] *= c; + } + } + } + else { + if(numtaps % 2) { + for(i = 0; i < gridsize; i++) { + c = sin(Pi2 * Grid[i]); + D[i] /= c; + W[i] *= c; + } + } + else { + for(i = 0; i < gridsize; i++) { + c = sin(Pi * Grid[i]); + D[i] /= c; + W[i] *= c; + } + } + } + + /* + * Perform the Remez Exchange algorithm + */ + for(iter = 0; iter < MAXITERATIONS; iter++) { + calc_parms(r, Ext, Grid, D, W, ad, x, y); + calc_error(r, ad, x, y, gridsize, Grid, D, W, E); + int err = search(r, Ext, gridsize, E); + if(err) + return err; + for(int i = 0; i <= r; i++) + assert(Ext[i] < gridsize); + if(is_done(r, Ext, E)) + break; + } + + calc_parms(r, Ext, Grid, D, W, ad, x, y); + + /* + * Find the 'taps' of the filter for use with Frequency + * Sampling. If odd or Negative symmetry, fix the taps + * according to Parks McClellan + */ + for(i = 0; i <= numtaps/2; i++) { + if(symmetry == POSITIVE) { + if(numtaps % 2) + c = 1; + else + c = cos(Pi * (double)i/numtaps); + } + else { + if(numtaps % 2) + c = sin(Pi2 * (double)i/numtaps); + else + c = sin(Pi * (double)i/numtaps); + } + taps[i] = compute_A((double)i/numtaps, r, ad, x, y)*c; + } + + /* + * Frequency sampling design with calculated taps + */ + freq_sample(numtaps, taps, h, symmetry); + + /* + * Delete allocated memory + */ + free(Grid); + free(W); + free(D); + free(E); + free(Ext); + free(x); + free(y); + free(ad); + + return iter<MAXITERATIONS?0:-1; + } + + ////////////////////////////////////////////////////////////////////////////// + // + // GNU Radio interface + // + ////////////////////////////////////////////////////////////////////////////// + + static void + punt(const std::string msg) + { + std::cerr << msg << '\n'; + throw std::runtime_error(msg); + } + + std::vector<double> + pm_remez(int order, + const std::vector<double> &arg_bands, + const std::vector<double> &arg_response, + const std::vector<double> &arg_weight, + const std::string filter_type, + int grid_density + ) throw (std::runtime_error) + { + int numtaps = order + 1; + if(numtaps < 4) + punt("gr_remez: number of taps must be >= 3"); + + int numbands = arg_bands.size() / 2; + LOCAL_BUFFER(double, bands, numbands * 2); + if(numbands < 1 || arg_bands.size() % 2 == 1) + punt("gr_remez: must have an even number of band edges"); + + for(unsigned int i = 1; i < arg_bands.size(); i++){ + if(arg_bands[i] < arg_bands[i-1]) + punt("gr_remez: band edges must be nondecreasing"); + } + + if(arg_bands[0] < 0 || arg_bands[arg_bands.size() - 1] > 1) + punt("gr_remez: band edges must be in the range [0,1]"); + + // Divide by 2 to fit with the implementation that uses a + // sample rate of [0, 0.5] instead of [0, 1.0] + for(int i = 0; i < 2 * numbands; i++) + bands[i] = arg_bands[i] / 2; + + LOCAL_BUFFER(double, response, numbands * 2); + if(arg_response.size() != arg_bands.size()) + punt("gr_remez: must have one response magnitude for each band edge"); + + for(int i = 0; i < 2 * numbands; i++) + response[i] = arg_response[i]; + + LOCAL_BUFFER(double, weight, numbands); + for(int i = 0; i < numbands; i++) + weight[i] = 1.0; + + if(arg_weight.size() != 0) { + if((int) arg_weight.size() != numbands) + punt("gr_remez: need one weight for each band [=length(band)/2]"); + for(int i = 0; i < numbands; i++) + weight[i] = arg_weight [i]; + } + + int itype = 0; + if(filter_type == "bandpass") + itype = BANDPASS; + else if(filter_type == "differentiator") + itype = DIFFERENTIATOR; + else if(filter_type == "hilbert") + itype = HILBERT; + else + punt("gr_remez: unknown ftype '" + filter_type + "'"); + + if(grid_density < 16) + punt("gr_remez: grid_density is too low; must be >= 16"); + + LOCAL_BUFFER(double, coeff, numtaps + 5); // FIXME why + 5? + int err = remez(coeff, numtaps, numbands, + bands, response, weight, itype, grid_density); + + if(err == -1) + punt("gr_remez: failed to converge"); + + if(err == -2) + punt("gr_remez: insufficient extremals -- cannot continue"); + + if(err == -3) + punt("gr_remez: too many extremals -- cannot continue"); + + return std::vector<double>(&coeff[0], &coeff[numtaps]); + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/polyphase_filterbank.cc b/gr-filter/lib/polyphase_filterbank.cc new file mode 100644 index 0000000000..046c23fc07 --- /dev/null +++ b/gr-filter/lib/polyphase_filterbank.cc @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <filter/polyphase_filterbank.h> +#include <cstdio> + +namespace gr { + namespace filter { + namespace kernel { + + polyphase_filterbank::polyphase_filterbank(unsigned int nfilts, + const std::vector<float> &taps) + : d_nfilts(nfilts) + { + d_filters = std::vector<kernel::fir_filter_ccf*>(d_nfilts); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilts); + for(unsigned int i = 0; i < d_nfilts; i++) { + d_filters[i] = new kernel::fir_filter_ccf(1, vtaps); + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the FFT to handle the output de-spinning of the channels + d_fft = new fft::fft_complex(d_nfilts, false); + } + + polyphase_filterbank::~polyphase_filterbank() + { + delete d_fft; + for(unsigned int i = 0; i < d_nfilts; i++) { + delete d_filters[i]; + } + } + + void + polyphase_filterbank::set_taps(const std::vector<float> &taps) + { + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilts); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_nfilts); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_nfilts*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilts; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_nfilts]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + } + + void + polyphase_filterbank::print_taps() + { + unsigned int i, j; + for(i = 0; i < d_nfilts; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } + } + + std::vector< std::vector<float> > + polyphase_filterbank::taps() const + { + return d_taps; + } + + } /* namespace kernel */ + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/qa_filter.cc b/gr-filter/lib/qa_filter.cc new file mode 100644 index 0000000000..b7760b19ea --- /dev/null +++ b/gr-filter/lib/qa_filter.cc @@ -0,0 +1,47 @@ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * This class gathers together all the test cases for the gr-filter + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include <qa_filter.h> +#include <qa_firdes.h> +#include <qa_fir_filter_with_buffer.h> +#include <qa_mmse_fir_interpolator_cc.h> +#include <qa_mmse_fir_interpolator_ff.h> + +CppUnit::TestSuite * +qa_gr_filter::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("gr-filter"); + + s->addTest(gr::filter::qa_firdes::suite()); + s->addTest(gr::filter::fff::qa_fir_filter_with_buffer_fff::suite()); + s->addTest(gr::filter::ccc::qa_fir_filter_with_buffer_ccc::suite()); + s->addTest(gr::filter::ccf::qa_fir_filter_with_buffer_ccf::suite()); + s->addTest(gr::filter::qa_mmse_fir_interpolator_cc::suite()); + s->addTest(gr::filter::qa_mmse_fir_interpolator_ff::suite()); + + return s; +} diff --git a/gr-filter/lib/qa_filter.h b/gr-filter/lib/qa_filter.h new file mode 100644 index 0000000000..427e7f9f6a --- /dev/null +++ b/gr-filter/lib/qa_filter.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _QA_GR_FILTER_H_ +#define _QA_GR_FILTER_H_ + +#include <gruel/attributes.h> +#include <cppunit/TestSuite.h> + +//! collect all the tests for the gr-filter directory + +class __GR_ATTR_EXPORT qa_gr_filter { + public: + //! return suite of tests for all of gr-filter directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_GR_FILTER_H_ */ diff --git a/gr-filter/lib/qa_fir_filter_with_buffer.cc b/gr-filter/lib/qa_fir_filter_with_buffer.cc new file mode 100644 index 0000000000..6a1744b0ac --- /dev/null +++ b/gr-filter/lib/qa_fir_filter_with_buffer.cc @@ -0,0 +1,406 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_types.h> +#include <qa_fir_filter_with_buffer.h> +#include <filter/fir_filter_with_buffer.h> +#include <fft/fft.h> +#include <cppunit/TestAssert.h> +#include <cmath> +#include <random.h> +#include <cstring> + +namespace gr { + namespace filter { + +#define MAX_DATA (16383) +#define ERR_DELTA (1e-5) + + static float + uniform() + { + return 2.0 * ((float) random() / RANDOM_MAX - 0.5); // uniformly (-1, 1) + } + + static void + random_floats(float *buf, unsigned n) + { + for(unsigned i = 0; i < n; i++) + buf[i] = (float)rint(uniform() * 32767); + } + + static void + random_complex(gr_complex *buf, unsigned n) + { + for(unsigned i = 0; i < n; i++) { + float re = rint(uniform() * MAX_DATA); + float im = rint(uniform() * MAX_DATA); + buf[i] = gr_complex(re, im); + } + } + + namespace fff { + + typedef float i_type; + typedef float o_type; + typedef float tap_type; + typedef float acc_type; + + using std::vector; + + static o_type + ref_dotprod(const i_type input[], const tap_type taps[], int ntaps) + { + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + return sum; + } + + void + qa_fir_filter_with_buffer_fff::t1() + { + test_decimate(1); + } + + void + qa_fir_filter_with_buffer_fff::t2() + { + test_decimate(2); + } + + void + qa_fir_filter_with_buffer_fff::t3() + { + test_decimate(5); + } + + // + // Test for ntaps in [0,9], and input lengths in [0,17]. + // This ensures that we are building the shifted taps correctly, + // and exercises all corner cases on input alignment and length. + // + void + qa_fir_filter_with_buffer_fff::test_decimate(unsigned int decimate) + { + const int MAX_TAPS = 29; + const int OUTPUT_LEN = 37; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = fft::malloc_float(INPUT_LEN); + i_type *dline = fft::malloc_float(INPUT_LEN); + o_type *expected_output = fft::malloc_float(OUTPUT_LEN); + o_type *actual_output = fft::malloc_float(OUTPUT_LEN); + tap_type *taps = fft::malloc_float(MAX_TAPS); + + srandom(0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for(int n = 0; n <= MAX_TAPS; n++) { + for(int ol = 0; ol <= OUTPUT_LEN; ol++) { + + // build random test case + random_floats(input, INPUT_LEN); + random_floats(taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for(int o = 0; o < (int)(ol/decimate); o++) { + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod(dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + kernel::fir_filter_with_buffer_fff *f1 = \ + new kernel::fir_filter_with_buffer_fff(f1_taps); + + // zero the output, then do the filtering + memset(actual_output, 0, OUTPUT_LEN*sizeof(o_type)); + f1->filterNdec(actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for(int o = 0; o < (int)(ol/decimate); o++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], + sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA); + } + delete f1; + } + } + fft::free(input); + fft::free(dline); + fft::free(expected_output); + fft::free(actual_output); + fft::free(taps); + } + + } /* namespace fff */ + + + /**************************************************************/ + + + namespace ccc { + + typedef gr_complex i_type; + typedef gr_complex o_type; + typedef gr_complex tap_type; + typedef gr_complex acc_type; + + using std::vector; + + static o_type + ref_dotprod(const i_type input[], const tap_type taps[], int ntaps) + { + acc_type sum = 0; + for(int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; + } + + void + qa_fir_filter_with_buffer_ccc::t1() + { + test_decimate(1); + } + + void + qa_fir_filter_with_buffer_ccc::t2() + { + test_decimate(2); + } + + void + qa_fir_filter_with_buffer_ccc::t3() + { + test_decimate(5); + } + + // + // Test for ntaps in [0,9], and input lengths in [0,17]. + // This ensures that we are building the shifted taps correctly, + // and exercises all corner cases on input alignment and length. + // + void + qa_fir_filter_with_buffer_ccc::test_decimate(unsigned int decimate) + { + const int MAX_TAPS = 29; + const int OUTPUT_LEN = 37; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = fft::malloc_complex(INPUT_LEN); + i_type *dline = fft::malloc_complex(INPUT_LEN); + o_type *expected_output = fft::malloc_complex(OUTPUT_LEN); + o_type *actual_output = fft::malloc_complex(OUTPUT_LEN); + tap_type *taps = fft::malloc_complex(MAX_TAPS); + + srandom(0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for(int n = 0; n <= MAX_TAPS; n++) { + for(int ol = 0; ol <= OUTPUT_LEN; ol++) { + + // build random test case + random_complex(input, INPUT_LEN); + random_complex(taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for(int o = 0; o < (int)(ol/decimate); o++) { + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod(dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + kernel::fir_filter_with_buffer_ccc *f1 = \ + new kernel::fir_filter_with_buffer_ccc(f1_taps); + + // zero the output, then do the filtering + memset(actual_output, 0, OUTPUT_LEN*sizeof(o_type)); + f1->filterNdec(actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for(int o = 0; o < (int)(ol/decimate); o++) { + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA); + } + delete f1; + } + } + fft::free(input); + fft::free(dline); + fft::free(expected_output); + fft::free(actual_output); + fft::free(taps); + } + + } /* namespace ccc */ + + + /**************************************************************/ + + namespace ccf { + + typedef gr_complex i_type; + typedef gr_complex o_type; + typedef float tap_type; + typedef gr_complex acc_type; + + using std::vector; + + static o_type + ref_dotprod(const i_type input[], const tap_type taps[], int ntaps) + { + acc_type sum = 0; + for(int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + //return gr_complex(121,9)*sum; + return sum; + } + + void + qa_fir_filter_with_buffer_ccf::t1() + { + test_decimate(1); + } + + void + qa_fir_filter_with_buffer_ccf::t2() + { + test_decimate(2); + } + + void + qa_fir_filter_with_buffer_ccf::t3() + { + test_decimate(5); + } + + // + // Test for ntaps in [0,9], and input lengths in [0,17]. + // This ensures that we are building the shifted taps correctly, + // and exercises all corner cases on input alignment and length. + // + void + qa_fir_filter_with_buffer_ccf::test_decimate(unsigned int decimate) + { + const int MAX_TAPS = 29; + const int OUTPUT_LEN = 37; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = fft::malloc_complex(INPUT_LEN); + i_type *dline = fft::malloc_complex(INPUT_LEN); + o_type *expected_output = fft::malloc_complex(OUTPUT_LEN); + o_type *actual_output = fft::malloc_complex(OUTPUT_LEN); + tap_type *taps = fft::malloc_float(MAX_TAPS); + + srandom(0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for(int n = 0; n <= MAX_TAPS; n++) { + for(int ol = 0; ol <= OUTPUT_LEN; ol++) { + + // build random test case + random_complex(input, INPUT_LEN); + random_floats(taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for(int o = 0; o < (int)(ol/decimate); o++) { + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod(dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + kernel::fir_filter_with_buffer_ccf *f1 = \ + new kernel::fir_filter_with_buffer_ccf(f1_taps); + + // zero the output, then do the filtering + memset(actual_output, 0, sizeof(actual_output)); + f1->filterNdec(actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for(int o = 0; o < (int)(ol/decimate); o++) { + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA); + } + delete f1; + } + } + fft::free(input); + fft::free(dline); + fft::free(expected_output); + fft::free(actual_output); + fft::free(taps); + } + + } /* namespace ccf */ + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/qa_fir_filter_with_buffer.h b/gr-filter/lib/qa_fir_filter_with_buffer.h new file mode 100644 index 0000000000..8850ada20c --- /dev/null +++ b/gr-filter/lib/qa_fir_filter_with_buffer.h @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +#ifndef _QA_FIR_FILTER_WITH_BUFFER_H_ +#define _QA_FIR_FILTER_WITH_BUFFER_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +namespace gr { + namespace filter { + + namespace fff { + + class qa_fir_filter_with_buffer_fff : public CppUnit::TestCase + { + CPPUNIT_TEST_SUITE(qa_fir_filter_with_buffer_fff); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); + + private: + void test_decimate(unsigned int decimate); + + void t1(); + void t2(); + void t3(); + }; + + } /* namespace fff */ + + namespace ccc { + + class qa_fir_filter_with_buffer_ccc : public CppUnit::TestCase + { + CPPUNIT_TEST_SUITE(qa_fir_filter_with_buffer_ccc); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); + + private: + void test_decimate(unsigned int decimate); + + void t1(); + void t2(); + void t3(); + }; + + } /* namespace ccc */ + + namespace ccf { + + class qa_fir_filter_with_buffer_ccf : public CppUnit::TestCase + { + CPPUNIT_TEST_SUITE(qa_fir_filter_with_buffer_ccf); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); + + private: + void test_decimate(unsigned int decimate); + + void t1(); + void t2(); + void t3(); + }; + + } /* namespace ccf */ + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* _QA_FIR_FILTER_WITH_BUFFER_H_ */ diff --git a/gr-filter/lib/qa_firdes.cc b/gr-filter/lib/qa_firdes.cc new file mode 100644 index 0000000000..c2fe399d5a --- /dev/null +++ b/gr-filter/lib/qa_firdes.cc @@ -0,0 +1,621 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <qa_firdes.h> +#include <filter/firdes.h> +#include <cppunit/TestAssert.h> +#include <gr_complex.h> +#include <string.h> +#include <iostream> +#include <iomanip> +#include <stdio.h> + +namespace gr { + namespace filter { + +#define NELEM(x) (sizeof(x) / sizeof(x[0])) + + using std::vector; + +#if 0 + static void + print_taps(std::ostream &s, vector<float> &v) + { + + for(unsigned int i = 0; i < v.size(); i++) { + printf("tap[%2d] = %16.7e\n", i, v[i]); + } + } +#endif + + static void + check_symmetry(vector<float> &v) + { + int n = v.size(); + int m = n / 2; + + for(int i = 0; i < m; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(v[i], v[n - i - 1], 1e-9); + } + + const static float t1_exp[53] = { + -9.0525491e-04, + 2.0713841e-04, + 1.2388536e-03, + 2.9683491e-04, + -1.7744775e-03, + -1.3599906e-03, + 2.2031884e-03, + 3.2744040e-03, + -1.8868084e-03, + -5.9935520e-03, + 6.4301129e-18, + 8.9516686e-03, + 4.2178580e-03, + -1.0998557e-02, + -1.1173409e-02, + 1.0455756e-02, + 2.0686293e-02, + -5.2032238e-03, + -3.1896964e-02, + -7.4998410e-03, + 4.3362070e-02, + 3.2502845e-02, + -5.3328082e-02, + -8.5621715e-02, + 6.0117975e-02, + 3.1128189e-01, + 4.3769023e-01, + 3.1128189e-01, + 6.0117975e-02, + -8.5621715e-02, + -5.3328082e-02, + 3.2502845e-02, + 4.3362070e-02, + -7.4998410e-03, + -3.1896964e-02, + -5.2032238e-03, + 2.0686293e-02, + 1.0455756e-02, + -1.1173409e-02, + -1.0998557e-02, + 4.2178580e-03, + 8.9516686e-03, + 6.4301129e-18, + -5.9935520e-03, + -1.8868084e-03, + 3.2744040e-03, + 2.2031884e-03, + -1.3599906e-03, + -1.7744775e-03, + 2.9683491e-04, + 1.2388536e-03, + 2.0713841e-04, + -9.0525491e-04 + }; + + const static float t2_exp[53] = { + 9.0380036e-04, + -2.0680559e-04, + -1.2368630e-03, + -2.9635796e-04, + 1.7716263e-03, + 1.3578053e-03, + -2.1996482e-03, + -3.2691427e-03, + 1.8837767e-03, + 5.9839217e-03, + -6.4197810e-18, + -8.9372853e-03, + -4.2110807e-03, + 1.0980885e-02, + 1.1155456e-02, + -1.0438956e-02, + -2.0653054e-02, + 5.1948633e-03, + 3.1845711e-02, + 7.4877902e-03, + -4.3292396e-02, + -3.2450620e-02, + 5.3242393e-02, + 8.5484132e-02, + -6.0021374e-02, + -3.1078172e-01, + 5.6184036e-01, + -3.1078172e-01, + -6.0021374e-02, + 8.5484132e-02, + 5.3242393e-02, + -3.2450620e-02, + -4.3292396e-02, + 7.4877902e-03, + 3.1845711e-02, + 5.1948633e-03, + -2.0653054e-02, + -1.0438956e-02, + 1.1155456e-02, + 1.0980885e-02, + -4.2110807e-03, + -8.9372853e-03, + -6.4197810e-18, + 5.9839217e-03, + 1.8837767e-03, + -3.2691427e-03, + -2.1996482e-03, + 1.3578053e-03, + 1.7716263e-03, + -2.9635796e-04, + -1.2368630e-03, + -2.0680559e-04, + 9.0380036e-04 + }; + + const static float t3_exp[107] = { + -1.8970841e-06, + -7.1057165e-04, + 5.4005696e-04, + 4.6233178e-04, + 2.0572044e-04, + 3.5209916e-04, + -1.4098573e-03, + 1.1279077e-04, + -6.2994129e-04, + 1.1450432e-03, + 1.3637283e-03, + -6.4360141e-04, + 3.6509900e-04, + -3.2864159e-03, + 7.0192874e-04, + 3.7524730e-04, + 2.0256115e-03, + 3.0641893e-03, + -3.6618244e-03, + 7.5592739e-05, + -5.5586505e-03, + 2.3849572e-03, + 4.0114378e-03, + 1.6636450e-03, + 4.7835698e-03, + -1.0191196e-02, + -3.8158931e-04, + -5.5551580e-03, + 5.3901658e-03, + 1.1366769e-02, + -3.0000482e-03, + 4.9341680e-03, + -2.0093076e-02, + 5.5752542e-17, + 1.2093617e-03, + 8.6089745e-03, + 2.2382140e-02, + -1.6854567e-02, + 1.6913920e-03, + -3.1222520e-02, + 3.2711059e-03, + 2.2604836e-02, + 8.1451107e-03, + 3.7583180e-02, + -5.2293688e-02, + -8.0551542e-03, + -4.0092729e-02, + 1.5582236e-02, + 9.7452506e-02, + -1.6183170e-02, + 8.3281815e-02, + -2.8196752e-01, + -1.0965768e-01, + 5.2867508e-01, + -1.0965768e-01, + -2.8196752e-01, + 8.3281815e-02, + -1.6183170e-02, + 9.7452506e-02, + 1.5582236e-02, + -4.0092729e-02, + -8.0551542e-03, + -5.2293688e-02, + 3.7583180e-02, + 8.1451107e-03, + 2.2604836e-02, + 3.2711059e-03, + -3.1222520e-02, + 1.6913920e-03, + -1.6854567e-02, + 2.2382140e-02, + 8.6089745e-03, + 1.2093617e-03, + 5.5752542e-17, + -2.0093076e-02, + 4.9341680e-03, + -3.0000482e-03, + 1.1366769e-02, + 5.3901658e-03, + -5.5551580e-03, + -3.8158931e-04, + -1.0191196e-02, + 4.7835698e-03, + 1.6636450e-03, + 4.0114378e-03, + 2.3849572e-03, + -5.5586505e-03, + 7.5592739e-05, + -3.6618244e-03, + 3.0641893e-03, + 2.0256115e-03, + 3.7524730e-04, + 7.0192874e-04, + -3.2864159e-03, + 3.6509900e-04, + -6.4360141e-04, + 1.3637283e-03, + 1.1450432e-03, + -6.2994129e-04, + 1.1279077e-04, + -1.4098573e-03, + 3.5209916e-04, + 2.0572044e-04, + 4.6233178e-04, + 5.4005696e-04, + -7.1057165e-04, + -1.8970841e-06 + }; + + const static float t4_exp[] = { // low pass + 0.001059958362, + 0.0002263929928, + -0.001277606934, + -0.0009675776237, + 0.001592264394, + 0.00243603508, + -0.001451682881, + -0.004769335967, + 5.281541594e-18, + 0.007567512803, + 0.003658855334, + -0.009761494584, + -0.01011830103, + 0.009636915289, + 0.0193619132, + -0.004935568199, + -0.03060629964, + -0.007267376408, + 0.04236677289, + 0.03197422624, + -0.05274848267, + -0.0850463286, + 0.05989059806, + 0.31065014, + 0.4370569289, + 0.31065014, + 0.05989059806, + -0.0850463286, + -0.05274848267, + 0.03197422624, + 0.04236677289, + -0.007267376408, + -0.03060629964, + -0.004935568199, + 0.0193619132, + 0.009636915289, + -0.01011830103, + -0.009761494584, + 0.003658855334, + 0.007567512803, + 5.281541594e-18, + -0.004769335967, + -0.001451682881, + 0.00243603508, + 0.001592264394, + -0.0009675776237, + -0.001277606934, + 0.0002263929928, + 0.001059958362, + }; + + const static float t5_exp[] = { //high pass + -0.001062123571, + -0.0002268554381, + 0.001280216733, + 0.000969554123, + -0.001595516922, + -0.002441011136, + 0.001454648213, + 0.004779078532, + -5.292330097e-18, + -0.007582970895, + -0.00366632943, + 0.009781434201, + 0.01013896987, + -0.009656600654, + -0.01940146461, + 0.004945650231, + 0.03066881932, + 0.00728222169, + -0.04245331511, + -0.03203954175, + 0.05285623297, + 0.08522006124, + -0.06001294032, + -0.3112847209, + 0.5630782247, + -0.3112847209, + -0.06001294032, + 0.08522006124, + 0.05285623297, + -0.03203954175, + -0.04245331511, + 0.00728222169, + 0.03066881932, + 0.004945650231, + -0.01940146461, + -0.009656600654, + 0.01013896987, + 0.009781434201, + -0.00366632943, + -0.007582970895, + -5.292330097e-18, + 0.004779078532, + 0.001454648213, + -0.002441011136, + -0.001595516922, + 0.000969554123, + 0.001280216733, + -0.0002268554381, + -0.001062123571, + }; + + const static float t6_exp[] = { // bandpass + 0.0002809273137, + -0.001047327649, + 7.936541806e-05, + -0.0004270860809, + 0.0007595835486, + 0.0008966081077, + -0.0004236323002, + 0.0002423936094, + -0.002212299034, + 0.0004807534278, + 0.0002620361629, + 0.001443728455, + 0.002229931997, + -0.002720607212, + 5.731141573e-05, + -0.004297634587, + 0.001878833398, + 0.003217151389, + 0.001357055153, + 0.003965090029, + -0.008576190099, + -0.0003257228818, + -0.004805727862, + 0.004721920472, + 0.01007549558, + -0.002688719891, + 0.004467967432, + -0.01837076992, + 5.119658377e-17, + 0.001125075156, + 0.008071650751, + 0.02113764361, + -0.01602453552, + 0.001618095324, + -0.03004053794, + 0.003163811285, + 0.0219683405, + 0.007950295694, + 0.03682873398, + -0.05142467469, + -0.00794606097, + -0.03965795785, + 0.01544955093, + 0.09681399167, + -0.01610304788, + 0.08297294378, + -0.2811714709, + -0.1094062924, + 0.5275565982, + -0.1094062924, + -0.2811714709, + 0.08297294378, + -0.01610304788, + 0.09681399167, + 0.01544955093, + -0.03965795785, + -0.00794606097, + -0.05142467469, + 0.03682873398, + 0.007950295694, + 0.0219683405, + 0.003163811285, + -0.03004053794, + 0.001618095324, + -0.01602453552, + 0.02113764361, + 0.008071650751, + 0.001125075156, + 5.119658377e-17, + -0.01837076992, + 0.004467967432, + -0.002688719891, + 0.01007549558, + 0.004721920472, + -0.004805727862, + -0.0003257228818, + -0.008576190099, + 0.003965090029, + 0.001357055153, + 0.003217151389, + 0.001878833398, + -0.004297634587, + 5.731141573e-05, + -0.002720607212, + 0.002229931997, + 0.001443728455, + 0.0002620361629, + 0.0004807534278, + -0.002212299034, + 0.0002423936094, + -0.0004236323002, + 0.0008966081077, + 0.0007595835486, + -0.0004270860809, + 7.936541806e-05, + -0.001047327649, + 0.0002809273137, + }; + + void + qa_firdes::t1() + { + vector<float> taps = + firdes::low_pass(1.0, + 8000, + 1750, + 500, + firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size() << endl; + // print_taps(cout, taps); + + CPPUNIT_ASSERT_EQUAL(NELEM(t1_exp), taps.size()); + for(unsigned int i = 0; i < taps.size(); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(t1_exp[i], taps[i], 1e-9); + + check_symmetry(taps); +} + + void + qa_firdes::t2() + { + vector<float> taps = + firdes::high_pass(1.0, + 8000, + 1750, + 500, + firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size() << endl; + // print_taps(cout, taps); + + CPPUNIT_ASSERT_EQUAL(NELEM(t2_exp), taps.size()); + + for(unsigned int i = 0; i < taps.size(); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(t2_exp[i], taps[i], 1e-9); + + check_symmetry(taps); + } + + void + qa_firdes::t3() + { + vector<float> taps = + firdes::band_pass(1.0, + 20e6, + 5.75e6 - (5.28e6/2), + 5.75e6 + (5.28e6/2), + 0.62e6, + firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size() << endl; + // print_taps(cout, taps); + + CPPUNIT_ASSERT_EQUAL(NELEM(t3_exp), taps.size()); + + for(unsigned int i = 0; i < taps.size(); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(t3_exp[i], taps[i], 1e-7); + + check_symmetry(taps); + } + + void + qa_firdes::t4() + { + vector<float> taps = + firdes::low_pass_2(1.0, + 8000, + 1750, + 500, + 66, + firdes::WIN_HAMMING); + + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); + + CPPUNIT_ASSERT_EQUAL(NELEM(t4_exp), taps.size()); + for(unsigned int i = 0; i < taps.size(); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(t4_exp[i], taps[i], 1e-9); + + check_symmetry(taps); + } + + void + qa_firdes::t5() + { + vector<float> taps = + firdes::high_pass_2(1.0, + 8000, + 1750, + 500, + 66, + firdes::WIN_HAMMING); + + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); + + CPPUNIT_ASSERT_EQUAL(NELEM(t5_exp), taps.size()); + + for(unsigned int i = 0; i < taps.size(); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(t5_exp[i], taps[i], 1e-9); + + check_symmetry(taps); +} + + void + qa_firdes::t6() + { + vector<float> taps = + firdes::band_pass_2(1.0, + 20e6, + 5.75e6 - (5.28e6/2), + 5.75e6 + (5.28e6/2), + 0.62e6, + 66, + firdes::WIN_HAMMING); + + // std::cout << "ntaps: " << taps.size() << std::endl; + // print_taps(std::cout, taps); + + CPPUNIT_ASSERT_EQUAL(NELEM(t6_exp), taps.size()); + + for(unsigned int i = 0; i < taps.size(); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL(t6_exp[i], taps[i], 1e-7); + + check_symmetry(taps); + } + + void + qa_firdes::t7() + { + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i b/gr-filter/lib/qa_firdes.h index 3dddb17c3e..b27cf78b91 100644 --- a/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i +++ b/gr-filter/lib/qa_firdes.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2002,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,13 +19,38 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ +#ifndef _QA_FILTER_FIRDES_H_ +#define _QA_FILTER_FIRDES_H_ -GR_SWIG_BLOCK_MAGIC(gr,diff_decoder_bb) +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> -gr_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); +namespace gr { + namespace filter { + + class qa_firdes : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE(qa_firdes); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST(t4); + CPPUNIT_TEST(t5); + CPPUNIT_TEST(t6); + CPPUNIT_TEST(t7); + CPPUNIT_TEST_SUITE_END(); + + private: + void t1(); + void t2(); + void t3(); + void t4(); + void t5(); + void t6(); + void t7(); + }; + + } /* namespace filter */ +} /* namespace gr */ -class gr_diff_decoder_bb : public gr_sync_block -{ - private: - gr_diff_decoder_bb (unsigned int modulus); -}; +#endif /* _QA_FILTER_FIRDES_H_ */ diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_cc.cc b/gr-filter/lib/qa_mmse_fir_interpolator_cc.cc new file mode 100644 index 0000000000..268b8801cc --- /dev/null +++ b/gr-filter/lib/qa_mmse_fir_interpolator_cc.cc @@ -0,0 +1,126 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <cppunit/TestAssert.h> +#include <qa_mmse_fir_interpolator_cc.h> +#include <filter/mmse_fir_interpolator_cc.h> +#include <fft/fft.h> +#include <cstdio> +#include <cmath> +#include <stdexcept> +#include <stdint.h> + +namespace gr { + namespace filter { + + static float + test_fcn_sin(double index) + { + return (2 * sin (index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * sin (index * 0.077 * 2 * M_PI + 0.3 * M_PI)); + } + + static float + test_fcn_cos(double index) + { + return (2 * cos (index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * cos (index * 0.077 * 2 * M_PI + 0.3 * M_PI)); + } + + static gr_complex + test_fcn(double index) + { + return gr_complex(test_fcn_cos(index), test_fcn_sin(index)); + } + + + void + qa_mmse_fir_interpolator_cc::t1() + { + static const unsigned N = 100; + gr_complex *input = fft::malloc_complex(N + 10); + + for(unsigned i = 0; i < N+10; i++) + input[i] = test_fcn((double) i); + + mmse_fir_interpolator_cc intr; + float inv_nsteps = 1.0 / intr.nsteps(); + + for(unsigned i = 0; i < N; i++) { + for(unsigned imu = 0; imu <= intr.nsteps (); imu += 1) { + gr_complex expected = test_fcn((i + 3) + imu * inv_nsteps); + gr_complex actual = intr.interpolate(&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } + fft::free(input); + } + + /* + * Force bad alignment and confirm that it raises an exception + */ + void + qa_mmse_fir_interpolator_cc::t2_body() + { + static const unsigned N = 100; + float float_input[2*(N+10) + 1]; + gr_complex *input; + + // We require that gr_complex be aligned on an 8-byte boundary. + // Ensure that we ARE NOT ;) + + if(((intptr_t) float_input & 0x7) == 0) + input = reinterpret_cast<gr_complex *>(&float_input[1]); + else + input = reinterpret_cast<gr_complex *>(&float_input[0]); + + for(unsigned i = 0; i < (N+10); i++) + input[i] = test_fcn((double) i); + + mmse_fir_interpolator_cc intr; + float inv_nsteps = 1.0 / intr.nsteps(); + + for(unsigned i = 0; i < N; i++) { + for(unsigned imu = 0; imu <= intr.nsteps (); imu += 1) { + gr_complex expected = test_fcn((i + 3) + imu * inv_nsteps); + gr_complex actual = intr.interpolate(&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } + } + + void + qa_mmse_fir_interpolator_cc::t2() + { + CPPUNIT_ASSERT_THROW(t2_body(), std::invalid_argument); + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_cc.h b/gr-filter/lib/qa_mmse_fir_interpolator_cc.h new file mode 100644 index 0000000000..a45965ca27 --- /dev/null +++ b/gr-filter/lib/qa_mmse_fir_interpolator_cc.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _QA_MMSE_FIR_INTERPOLATOR_CC_H_ +#define _QA_MMSE_FIR_INTERPOLATOR_CC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +namespace gr { + namespace filter { + + class qa_mmse_fir_interpolator_cc : public CppUnit::TestCase + { + CPPUNIT_TEST_SUITE(qa_mmse_fir_interpolator_cc); + CPPUNIT_TEST(t1); + // CPPUNIT_TEST(t2); + CPPUNIT_TEST_SUITE_END(); + + private: + void t1(); + void t2(); + void t2_body(); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* _QA_MMSE_FIR_INTERPOLATOR_CC_H_ */ diff --git a/gr-filter/lib/qa_mmse_fir_interpolator_ff.cc b/gr-filter/lib/qa_mmse_fir_interpolator_ff.cc new file mode 100644 index 0000000000..54387fd9bd --- /dev/null +++ b/gr-filter/lib/qa_mmse_fir_interpolator_ff.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <cppunit/TestAssert.h> +#include <qa_mmse_fir_interpolator_ff.h> +#include <filter/mmse_fir_interpolator_ff.h> +#include <fft/fft.h> +#include <cstdio> +#include <cmath> + +namespace gr { + namespace filter { + + static float + test_fcn(double index) + { + return (2 * sin(index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * sin(index * 0.077 * 2 * M_PI + 0.3 * M_PI)); + } + + void + qa_mmse_fir_interpolator_ff::t1() + { + // use aligned malloc and make sure that everything in this + // buffer is properly initialized. + static const unsigned N = 100; + float *input = fft::malloc_float(N + 10); + + for(unsigned i = 0; i < N+10; i++) + input[i] = test_fcn((double) i); + + mmse_fir_interpolator_ff intr; + float inv_nsteps = 1.0 / intr.nsteps(); + + for(unsigned i = 0; i < N; i++) { + for(unsigned imu = 0; imu <= intr.nsteps (); imu += 1) { + float expected = test_fcn((i + 3) + imu * inv_nsteps); + float actual = intr.interpolate(&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } + fft::free(input); + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gnuradio-core/src/lib/general/qa_gri_lfsr.h b/gr-filter/lib/qa_mmse_fir_interpolator_ff.h index e91843bbb3..833ec173ac 100644 --- a/gnuradio-core/src/lib/general/qa_gri_lfsr.h +++ b/gr-filter/lib/qa_mmse_fir_interpolator_ff.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2002,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,24 +19,27 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#ifndef _QA_GRI_LFSR_H_ -#define _QA_GRI_LFSR_H_ + +#ifndef _QA_MMSE_FIR_INTERPOLATOR_FF_H_ +#define _QA_MMSE_FIR_INTERPOLATOR_FF_H_ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gri_lfsr : public CppUnit::TestCase { +namespace gr { + namespace filter { + + class qa_mmse_fir_interpolator_ff : public CppUnit::TestCase + { + CPPUNIT_TEST_SUITE(qa_mmse_fir_interpolator_ff); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END(); - CPPUNIT_TEST_SUITE(qa_gri_lfsr); - CPPUNIT_TEST(test_lfsr); - CPPUNIT_TEST(test_scrambler); - CPPUNIT_TEST(test_descrambler); - CPPUNIT_TEST_SUITE_END(); + private: + void t1(); + }; - private: - void test_lfsr(); - void test_scrambler(); - void test_descrambler(); -}; + } /* namespace filter */ +} /* namespace gr */ -#endif /* _QA_GRI_LFSR_H_ */ +#endif /* _QA_MMSE_FIR_INTERPOLATOR_FF_H_ */ diff --git a/gr-filter/lib/rational_resampler_base_XXX_impl.cc.t b/gr-filter/lib/rational_resampler_base_XXX_impl.cc.t new file mode 100644 index 0000000000..2e9161eeb8 --- /dev/null +++ b/gr-filter/lib/rational_resampler_base_XXX_impl.cc.t @@ -0,0 +1,174 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "@IMPL_NAME@.h" +#include <gr_io_signature.h> +#include <volk/volk.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + @BASE_NAME@::sptr + @BASE_NAME@::make(unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(interpolation, decimation, taps)); + } + + @IMPL_NAME@::@IMPL_NAME@(unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_history(1), + d_interpolation(interpolation), + d_decimation(decimation), + d_ctr(0), + d_firs(interpolation), + d_updated(false) + { + if(interpolation == 0) + throw std::out_of_range("@IMPL_NAME@: interpolation must be > 0"); + if(decimation == 0) + throw std::out_of_range("@IMPL_NAME@: decimation must be > 0"); + + set_relative_rate(1.0 * interpolation / decimation); + set_output_multiple(1); + + std::vector<@TAP_TYPE@> dummy_taps; + + for(unsigned i = 0; i < interpolation; i++) { + d_firs[i] = new kernel::@FIR_TYPE@(1, dummy_taps); + } + + set_taps(taps); + install_taps(d_new_taps); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + int interp = interpolation(); + for(int i = 0; i < interp; i++) { + delete d_firs[i]; + } + } + + void + @IMPL_NAME@::set_taps(const std::vector<@TAP_TYPE@> &taps) + { + d_new_taps = taps; + d_updated = true; + + // round up length to a multiple of the interpolation factor + int n = taps.size() % interpolation(); + if(n > 0) { + n = interpolation() - n; + while(n-- > 0) { + d_new_taps.insert(d_new_taps.begin(), 0); + } + } + + assert(d_new_taps.size() % interpolation() == 0); + } + + void + @IMPL_NAME@::install_taps(const std::vector<@TAP_TYPE@> &taps) + { + int nfilters = interpolation(); + int nt = taps.size() / nfilters; + + assert(nt * nfilters == (int) taps.size()); + + std::vector< std::vector <@TAP_TYPE@> > xtaps(nfilters); + + for(int n = 0; n < nfilters; n++) + xtaps[n].resize (nt); + + for(int i = 0; i < (int)taps.size(); i++) + xtaps[i % nfilters][i / nfilters] = taps[i]; + + for(int n = 0; n < nfilters; n++) + d_firs[n]->set_taps(xtaps[n]); + + set_history(nt); + d_updated = false; + } + + std::vector<@TAP_TYPE@> + @IMPL_NAME@::taps() const + { + return d_new_taps; + } + + void + @IMPL_NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + int nreqd = std::max((unsigned)1, (int)((double) (noutput_items+1) * \ + decimation() / interpolation()) + history() - 1); + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = nreqd; + } + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const @I_TYPE@ *in = (const @I_TYPE@ *)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *)output_items[0]; + + if(d_updated) { + install_taps(d_new_taps); + return 0; // history requirement may have increased. + } + + unsigned int ctr = d_ctr; + + int i = 0; + while(i < noutput_items) { + out[i++] = d_firs[ctr]->filter(in); + ctr += decimation(); + while(ctr >= interpolation()) { + ctr -= interpolation(); + in++; + } + } + + d_ctr = ctr; + consume_each(in - (@I_TYPE@*)input_items[0]); + return i; + } + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/rational_resampler_base_XXX_impl.h.t b/gr-filter/lib/rational_resampler_base_XXX_impl.h.t new file mode 100644 index 0000000000..4396656da2 --- /dev/null +++ b/gr-filter/lib/rational_resampler_base_XXX_impl.h.t @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* @WARNING@ */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <filter/fir_filter.h> +#include <filter/@BASE_NAME@.h> + +namespace gr { + namespace filter { + + class FILTER_API @IMPL_NAME@ : public @BASE_NAME@ + { + private: + unsigned d_history; + unsigned d_interpolation; + unsigned d_decimation; + unsigned d_ctr; + std::vector<@TAP_TYPE@> d_new_taps; + std::vector<kernel::@FIR_TYPE@ *> d_firs; + bool d_updated; + + void install_taps(const std::vector<@TAP_TYPE@> &taps); + + public: + @IMPL_NAME@(unsigned interpolation, unsigned decimation, + const std::vector<@TAP_TYPE@> &taps); + + ~@IMPL_NAME@(); + + unsigned history() const { return d_history; } + void set_history(unsigned history) { d_history = history; } + + unsigned interpolation() const { return d_interpolation; } + unsigned decimation() const { return d_decimation; } + + void set_taps(const std::vector<@TAP_TYPE@> &taps); + std::vector<@TAP_TYPE@> taps() const; + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-filter/lib/single_pole_iir_filter_cc_impl.cc b/gr-filter/lib/single_pole_iir_filter_cc_impl.cc new file mode 100644 index 0000000000..9406f2c98a --- /dev/null +++ b/gr-filter/lib/single_pole_iir_filter_cc_impl.cc @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "single_pole_iir_filter_cc_impl.h" +#include <gr_io_signature.h> + + +namespace gr { + namespace filter { + + single_pole_iir_filter_cc::sptr + single_pole_iir_filter_cc::make(double alpha, unsigned int vlen) + { + return gnuradio::get_initial_sptr + (new single_pole_iir_filter_cc_impl(alpha, vlen)); + } + + single_pole_iir_filter_cc_impl::single_pole_iir_filter_cc_impl + (double alpha, unsigned int vlen) + : gr_sync_block("single_pole_iir_filter_cc", + gr_make_io_signature(1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature(1, 1, sizeof (gr_complex) * vlen)), + d_vlen(vlen), d_iir(vlen) + { + set_taps(alpha); + } + + single_pole_iir_filter_cc_impl::~single_pole_iir_filter_cc_impl() + { + } + + void + single_pole_iir_filter_cc_impl::set_taps(double alpha) + { + for(unsigned int i = 0; i < d_vlen; i++) { + d_iir[i].set_taps(alpha); + } + } + + int + single_pole_iir_filter_cc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const gr_complex *in = (const gr_complex*)input_items[0]; + gr_complex *out = (gr_complex*)output_items[0]; + unsigned int vlen = d_vlen; + + if(d_vlen == 1) { + for(int i = 0; i < noutput_items; i++) { + out[i] = d_iir[0].filter(in[i]); + } + } + else { + for(int i = 0; i < noutput_items; i++) { + for(unsigned int j = 0; j < vlen; j++) { + *out++ = d_iir[j].filter(*in++); + } + } + } + + return noutput_items; + }; + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/single_pole_iir_filter_cc_impl.h b/gr-filter/lib/single_pole_iir_filter_cc_impl.h new file mode 100644 index 0000000000..fa627881e5 --- /dev/null +++ b/gr-filter/lib/single_pole_iir_filter_cc_impl.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004-2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H +#define INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H + +#include <filter/single_pole_iir.h> +#include <filter/single_pole_iir_filter_cc.h> +#include <gr_sync_block.h> +#include <gr_complex.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + class FILTER_API single_pole_iir_filter_cc_impl : public single_pole_iir_filter_cc + { + private: + unsigned int d_vlen; + std::vector<single_pole_iir<gr_complex,gr_complex,double> > d_iir; + + public: + single_pole_iir_filter_cc_impl(double alpha, unsigned int vlen); + ~single_pole_iir_filter_cc_impl(); + + void set_taps(double alpha); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_CC_IMPL_H */ diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.cc b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc new file mode 100644 index 0000000000..7e2bae5db7 --- /dev/null +++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "single_pole_iir_filter_ff_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace filter { + + single_pole_iir_filter_ff::sptr + single_pole_iir_filter_ff::make(double alpha, unsigned int vlen) + { + return gnuradio::get_initial_sptr + (new single_pole_iir_filter_ff_impl(alpha, vlen)); + } + + single_pole_iir_filter_ff_impl::single_pole_iir_filter_ff_impl + (double alpha, unsigned int vlen) + : gr_sync_block("single_pole_iir_filter_ff", + gr_make_io_signature(1, 1, sizeof(float)*vlen), + gr_make_io_signature(1, 1, sizeof(float)*vlen)), + d_vlen(vlen), d_iir(vlen) + { + set_taps(alpha); + } + + single_pole_iir_filter_ff_impl::~single_pole_iir_filter_ff_impl() + { + } + + void + single_pole_iir_filter_ff_impl::set_taps(double alpha) + { + for(unsigned int i = 0; i < d_vlen; i++) { + d_iir[i].set_taps(alpha); + } + } + + int + single_pole_iir_filter_ff_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float*)input_items[0]; + float *out = (float*)output_items[0]; + unsigned int vlen = d_vlen; + + if(d_vlen == 1) { + for(int i = 0; i < noutput_items; i++) { + out[i] = d_iir[0].filter (in[i]); + } + } + else { + for(int i = 0; i < noutput_items; i++) { + for(unsigned int j = 0; j < vlen; j++) { + *out++ = d_iir[j].filter(*in++); + } + } + } + return noutput_items; + }; + + } /* namespace filter */ +} /* namespace gr */ diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.h b/gr-filter/lib/single_pole_iir_filter_ff_impl.h new file mode 100644 index 0000000000..cba9c188c2 --- /dev/null +++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004-2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H +#define INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H + +#include <filter/single_pole_iir.h> +#include <filter/single_pole_iir_filter_ff.h> +#include <gr_sync_block.h> +#include <stdexcept> + +namespace gr { + namespace filter { + + class FILTER_API single_pole_iir_filter_ff_impl : public single_pole_iir_filter_ff + { + private: + unsigned int d_vlen; + std::vector<single_pole_iir<float,float,double> > d_iir; + + public: + single_pole_iir_filter_ff_impl(double alpha, unsigned int vlen); + ~single_pole_iir_filter_ff_impl(); + + void set_taps(double alpha); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace filter */ +} /* namespace gr */ + +#endif /* INCLUDED_SINGLE_POLE_IIR_FILTER_FF_IMPL_H */ diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.i b/gr-filter/lib/test_gr_filter.cc index d1290f9d39..915b6286bd 100644 --- a/gnuradio-core/src/lib/general/gr_packet_sink.i +++ b/gr-filter/lib/test_gr_filter.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,22 +20,24 @@ * Boston, MA 02110-1301, USA. */ -GR_SWIG_BLOCK_MAGIC(gr,packet_sink) +#include <cppunit/TextTestRunner.h> +#include <cppunit/XmlOutputter.h> -gr_packet_sink_sptr -gr_make_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold = -1 // -1 -> use default - ); +#include <gr_unittests.h> +#include <qa_filter.h> +#include <iostream> -class gr_packet_sink : public gr_sync_block +int +main (int argc, char **argv) { - protected: - gr_packet_sink (const std::vector<unsigned char>& sync_vector, - gr_msg_queue_sptr target_queue, - int threshold); - public: - ~gr_packet_sink (); + CppUnit::TextTestRunner runner; + std::ofstream xmlfile(get_unittest_path("gr_filter.xml").c_str()); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); - bool carrier_sensed() const; -}; + runner.addTest(qa_gr_filter::suite()); + runner.setOutputter(xmlout); + + bool was_successful = runner.run("", false); + + return was_successful ? 0 : 1; +} diff --git a/gr-filter/python/CMakeLists.txt b/gr-filter/python/CMakeLists.txt new file mode 100644 index 0000000000..07f03fac4c --- /dev/null +++ b/gr-filter/python/CMakeLists.txt @@ -0,0 +1,50 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +include(GrPython) + +GR_PYTHON_INSTALL( + FILES + __init__.py + optfir.py + pfb.py + rational_resampler.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/filter + COMPONENT "filter_python" +) + +######################################################################## +# Handle the unit tests +######################################################################## +if(ENABLE_TESTING) +include(GrTest) +file(GLOB py_qa_test_files "qa_*.py") +foreach(py_qa_test_file ${py_qa_test_files}) + get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) + set(GR_TEST_PYTHON_DIRS + ${CMAKE_BINARY_DIR}/gnuradio-core/src/python + ${CMAKE_BINARY_DIR}/gnuradio-core/src/lib/swig + ${CMAKE_BINARY_DIR}/gr-filter/python + ${CMAKE_BINARY_DIR}/gr-filter/swig + ) + set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-filter) + GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file}) +endforeach(py_qa_test_file) +endif(ENABLE_TESTING) diff --git a/gr-filter/python/__init__.py b/gr-filter/python/__init__.py new file mode 100644 index 0000000000..65a62d828d --- /dev/null +++ b/gr-filter/python/__init__.py @@ -0,0 +1,30 @@ +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +''' +This is the gr-filter package. This package provides GNU Radio +processing blocks for FILTER and related functions. +''' + +from filter_swig import * +from rational_resampler import * +import pfb +import optfir diff --git a/gr-filter/python/optfir.py b/gr-filter/python/optfir.py new file mode 100644 index 0000000000..bccb8c68d0 --- /dev/null +++ b/gr-filter/python/optfir.py @@ -0,0 +1,339 @@ +# +# Copyright 2004,2005,2009 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +''' +Routines for designing optimal FIR filters. + +For a great intro to how all this stuff works, see section 6.6 of +"Digital Signal Processing: A Practical Approach", Emmanuael C. Ifeachor +and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X. +''' + +import math, cmath +import filter_swig as filter + +# ---------------------------------------------------------------- + +## Builds a low pass filter. +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq1 End of pass band (in Hz) +# @param freq2 Start of stop band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (gain, 0) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [passband_dev, stopband_dev], Fs) + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +## Builds a band pass filter. +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq_sb1 End of stop band (in Hz) +# @param freq_pb1 Start of pass band (in Hz) +# @param freq_pb2 End of pass band (in Hz) +# @param freq_sb2 Start of stop band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2, + passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (0, gain, 0) + desired_freqs = [freq_sb1, freq_pb1, freq_pb2, freq_sb2] + desired_ripple = [stopband_dev, passband_dev, stopband_dev] + (n, fo, ao, w) = remezord (desired_freqs, desired_ampls, + desired_ripple, Fs) + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + + +## Builds a band pass filter with complex taps by making an LPF and +# spinning it up to the right center frequency +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq_sb1 End of stop band (in Hz) +# @param freq_pb1 Start of pass band (in Hz) +# @param freq_pb2 End of pass band (in Hz) +# @param freq_sb2 Start of stop band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def complex_band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2, + passband_ripple_db, stopband_atten_db, + nextra_taps=2): + center_freq = (freq_pb2 + freq_pb1) / 2.0 + lp_pb = (freq_pb2 - center_freq)/1.0 + lp_sb = freq_sb2 - center_freq + lptaps = low_pass(gain, Fs, lp_pb, lp_sb, passband_ripple_db, + stopband_atten_db, nextra_taps) + spinner = [cmath.exp(2j*cmath.pi*center_freq/Fs*i) for i in xrange(len(lptaps))] + taps = [s*t for s,t in zip(spinner, lptaps)] + return taps + + +## Builds a band reject filter +# spinning it up to the right center frequency +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq_pb1 End of pass band (in Hz) +# @param freq_sb1 Start of stop band (in Hz) +# @param freq_sb2 End of stop band (in Hz) +# @param freq_pb2 Start of pass band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def band_reject (gain, Fs, freq_pb1, freq_sb1, freq_sb2, freq_pb2, + passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (gain, 0, gain) + desired_freqs = [freq_pb1, freq_sb1, freq_sb2, freq_pb2] + desired_ripple = [passband_dev, stopband_dev, passband_dev] + (n, fo, ao, w) = remezord (desired_freqs, desired_ampls, + desired_ripple, Fs) + # Make sure we use an odd number of taps + if((n+nextra_taps)%2 == 1): + n += 1 + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + + +## Builds a high pass filter. +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq1 End of stop band (in Hz) +# @param freq2 Start of pass band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def high_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (0, 1) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [stopband_dev, passband_dev], Fs) + # For a HPF, we need to use an odd number of taps + # In filter.remez, ntaps = n+1, so n must be even + if((n+nextra_taps)%2 == 1): + n += 1 + + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = filter.pm_remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +# ---------------------------------------------------------------- + +def stopband_atten_to_dev (atten_db): + """Convert a stopband attenuation in dB to an absolute value""" + return 10**(-atten_db/20) + +def passband_ripple_to_dev (ripple_db): + """Convert passband ripple spec expressed in dB to an absolute value""" + return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + +# ---------------------------------------------------------------- + +def remezord (fcuts, mags, devs, fsamp = 2): + ''' + FIR order estimator (lowpass, highpass, bandpass, mulitiband). + + (n, fo, ao, w) = remezord (f, a, dev) + (n, fo, ao, w) = remezord (f, a, dev, fs) + + (n, fo, ao, w) = remezord (f, a, dev) finds the approximate order, + normalized frequency band edges, frequency band amplitudes, and + weights that meet input specifications f, a, and dev, to use with + the remez command. + + * f is a sequence of frequency band edges (between 0 and Fs/2, where + Fs is the sampling frequency), and a is a sequence specifying the + desired amplitude on the bands defined by f. The length of f is + twice the length of a, minus 2. The desired function is + piecewise constant. + + * dev is a sequence the same size as a that specifies the maximum + allowable deviation or ripples between the frequency response + and the desired amplitude of the output filter, for each band. + + Use remez with the resulting order n, frequency sequence fo, + amplitude response sequence ao, and weights w to design the filter b + which approximately meets the specifications given by remezord + input parameters f, a, and dev: + + b = remez (n, fo, ao, w) + + (n, fo, ao, w) = remezord (f, a, dev, Fs) specifies a sampling frequency Fs. + + Fs defaults to 2 Hz, implying a Nyquist frequency of 1 Hz. You can + therefore specify band edges scaled to a particular applications + sampling frequency. + + In some cases remezord underestimates the order n. If the filter + does not meet the specifications, try a higher order such as n+1 + or n+2. + ''' + # get local copies + fcuts = fcuts[:] + mags = mags[:] + devs = devs[:] + + for i in range (len (fcuts)): + fcuts[i] = float (fcuts[i]) / fsamp + + nf = len (fcuts) + nm = len (mags) + nd = len (devs) + nbands = nm + + if nm != nd: + raise ValueError, "Length of mags and devs must be equal" + + if nf != 2 * (nbands - 1): + raise ValueError, "Length of f must be 2 * len (mags) - 2" + + for i in range (len (mags)): + if mags[i] != 0: # if not stopband, get relative deviation + devs[i] = devs[i] / mags[i] + + # separate the passband and stopband edges + f1 = fcuts[0::2] + f2 = fcuts[1::2] + + n = 0 + min_delta = 2 + for i in range (len (f1)): + if f2[i] - f1[i] < min_delta: + n = i + min_delta = f2[i] - f1[i] + + if nbands == 2: + # lowpass or highpass case (use formula) + l = lporder (f1[n], f2[n], devs[0], devs[1]) + else: + # bandpass or multipass case + # try different lowpasses and take the worst one that + # goes through the BP specs + l = 0 + for i in range (1, nbands-1): + l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1]) + l2 = lporder (f1[i], f2[i], devs[i], devs[i+1]) + l = max (l, l1, l2) + + n = int (math.ceil (l)) - 1 # need order, not length for remez + + # cook up remez compatible result + ff = [0] + fcuts + [1] + for i in range (1, len (ff) - 1): + ff[i] *= 2 + + aa = [] + for a in mags: + aa = aa + [a, a] + + max_dev = max (devs) + wts = [1] * len(devs) + for i in range (len (wts)): + wts[i] = max_dev / devs[i] + + return (n, ff, aa, wts) + +# ---------------------------------------------------------------- + +def lporder (freq1, freq2, delta_p, delta_s): + ''' + FIR lowpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + Note, this works for high pass filters too (freq1 > freq2), but + doesnt work well if the transition is near f == 0 or f == fs/2 + + From Herrmann et al (1973), Practical design rules for optimum + finite impulse response filters. Bell System Technical J., 52, 769-99 + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 5.309e-3 + a2 = 7.114e-2 + a3 = -4.761e-1 + a4 = -2.66e-3 + a5 = -5.941e-1 + a6 = -4.278e-1 + + b1 = 11.01217 + b2 = 0.5124401 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6) + ff = b1 + b2 * (ddp - dds) + n = dinf / df - ff * df + 1 + return n + + +def bporder (freq1, freq2, delta_p, delta_s): + ''' + FIR bandpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + From Mintzer and Liu (1979) + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 0.01201 + a2 = 0.09664 + a3 = -0.51325 + a4 = 0.00203 + a5 = -0.57054 + a6 = -0.44314 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + cinf = dds * (t1 + t2 + a3) + t3 + t4 + a6 + ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9 + n = cinf / df + ginf * df + 1 + return n + diff --git a/gr-filter/python/pfb.py b/gr-filter/python/pfb.py new file mode 100644 index 0000000000..ddf2899826 --- /dev/null +++ b/gr-filter/python/pfb.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python +# +# Copyright 2009,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr +import filter_swig as filter +import optfir + +class channelizer_ccf(gr.hier_block2): + ''' + Make a Polyphase Filter channelizer (complex in, complex out, floating-point taps) + + This simplifies the interface by allowing a single input stream to connect to this block. + It will then output a stream for each channel. + ''' + def __init__(self, numchans, taps=None, oversample_rate=1, atten=100): + gr.hier_block2.__init__(self, "pfb_channelizer_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(numchans, numchans, gr.sizeof_gr_complex)) + + self._nchans = numchans + self._oversample_rate = oversample_rate + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + made = False + while not made: + try: + self._taps = optfir.low_pass(1, self._nchans, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._nchans) + self.pfb = filter.pfb_channelizer_ccf(self._nchans, self._taps, + self._oversample_rate) + self.connect(self, self.s2ss) + + for i in xrange(self._nchans): + self.connect((self.s2ss,i), (self.pfb,i)) + self.connect((self.pfb,i), (self,i)) + + def set_channel_map(self, newmap): + self.pfb.set_channel_map(newmap) + + + +class interpolator_ccf(gr.hier_block2): + ''' + Make a Polyphase Filter interpolator (complex in, complex out, floating-point taps) + + The block takes a single complex stream in and outputs a single complex + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, interp, taps=None, atten=100): + gr.hier_block2.__init__(self, "pfb_interpolator_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + + self._interp = interp + self._taps = taps + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.99 + made = False + while not made: + try: + self._taps = optfir.low_pass(self._interp, self._interp, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = filter.pfb_interpolator_ccf(self._interp, self._taps) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + +class decimator_ccf(gr.hier_block2): + ''' + Make a Polyphase Filter decimator (complex in, complex out, floating-point taps) + + This simplifies the interface by allowing a single input stream to connect to this block. + It will then output a stream that is the decimated output stream. + ''' + def __init__(self, decim, taps=None, channel=0, atten=100): + gr.hier_block2.__init__(self, "pfb_decimator_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + + self._decim = decim + self._channel = channel + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + made = False + while not made: + try: + self._taps = optfir.low_pass(1, self._decim, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._decim) + self.pfb = filter.pfb_decimator_ccf(self._decim, self._taps, self._channel) + + self.connect(self, self.s2ss) + + for i in xrange(self._decim): + self.connect((self.s2ss,i), (self.pfb,i)) + + self.connect(self.pfb, self) + + +class arb_resampler_ccf(gr.hier_block2): + ''' + Convenience wrapper for the polyphase filterbank arbitrary resampler. + + The block takes a single complex stream in and outputs a single complex + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, rate, taps=None, flt_size=32, atten=100): + gr.hier_block2.__init__(self, "pfb_arb_resampler_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + self._rate = rate + self._size = flt_size + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + #self._taps = filter.firdes.low_pass_2(self._size, self._size, bw, tb, atten) + made = False + while not made: + try: + self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = filter.pfb_arb_resampler_ccf(self._rate, self._taps, self._size) + #print "PFB has %d taps\n" % (len(self._taps),) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + # Note -- set_taps not implemented in base class yet + def set_taps(self, taps): + self.pfb.set_taps(taps) + + def set_rate(self, rate): + self.pfb.set_rate(rate) + + +class arb_resampler_fff(gr.hier_block2): + ''' + Convenience wrapper for the polyphase filterbank arbitrary resampler. + + The block takes a single float stream in and outputs a single float + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, rate, taps=None, flt_size=32, atten=100): + gr.hier_block2.__init__(self, "pfb_arb_resampler_fff", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + self._rate = rate + self._size = flt_size + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + #self._taps = filter.firdes.low_pass_2(self._size, self._size, bw, tb, atten) + made = False + while not made: + try: + self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = filter.pfb_arb_resampler_fff(self._rate, self._taps, self._size) + #print "PFB has %d taps\n" % (len(self._taps),) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + # Note -- set_taps not implemented in base class yet + def set_taps(self, taps): + self.pfb.set_taps(taps) + + def set_rate(self, rate): + self.pfb.set_rate(rate) diff --git a/gr-filter/python/qa_adaptive_fir_filter.py b/gr-filter/python/qa_adaptive_fir_filter.py new file mode 100755 index 0000000000..cadce52044 --- /dev/null +++ b/gr-filter/python/qa_adaptive_fir_filter.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python +# +# Copyright 2008,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter + +class test_adaptive_filter(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_adaptive_fir_filter_ccf_001(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((0.5+0.5j), (1.5+1.5j), (3+3j), (5+5j), (5.5+5.5j), + (6.5+6.5j), (8+8j), (10+10j), (10.5+10.5j), (11.5+11.5j), + (13+13j), (15+15j), (15.5+15.5j), (16.5+16.5j), (18+18j), + (20+20j), (20.5+20.5j), (21.5+21.5j), (23+23j), (25+25j), + (25.5+25.5j), (26.5+26.5j), (28+28j), (30+30j), (30.5+30.5j), + (31.5+31.5j), (33+33j), (35+35j), (35.5+35.5j), (36.5+36.5j), + (38+38j), (40+40j), (40.5+40.5j), (41.5+41.5j), (43+43j), + (45+45j), (45.5+45.5j), (46.5+46.5j), (48+48j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j)) + + src = gr.vector_source_c(src_data) + op = filter.adaptive_fir_ccf("test", 1, 20*[0.5, 0.5]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + def test_adaptive_fir_filter_ccf_002(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((0.5+0.5j), (5.5+5.5j), (10.5+10.5j), (15.5+15.5j), + (20.5+20.5j), (25.5+25.5j), (30.5+30.5j), (35.5+35.5j), + (40.5+40.5j), (45.5+45.5j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j)) + + src = gr.vector_source_c(src_data) + op = filter.adaptive_fir_ccf("test", 4, 20*[0.5, 0.5]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + def test_adaptive_fir_filter_ccc_001(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((-0.5+1.5j), (-1.5+4.5j), (-3+9j), (-5+15j), + (-5.5+16.5j), (-6.5+19.5j), (-8+24j), (-10+30j), + (-10.5+31.5j), (-11.5+34.5j), (-13+39j), (-15+45j), + (-15.5+46.5j), (-16.5+49.5j), (-18+54j), (-20+60j), + (-20.5+61.5j), (-21.5+64.5j), (-23+69j), (-25+75j), + (-25.5+76.5j), (-26.5+79.5j), (-28+84j), (-30+90j), + (-30.5+91.5j), (-31.5+94.5j), (-33+99j), (-35+105j), + (-35.5+106.5j), (-36.5+109.5j), (-38+114j), (-40+120j), + (-40.5+121.5j), (-41.5+124.5j), (-43+129j), (-45+135j), + (-45.5+136.5j), (-46.5+139.5j), (-48+144j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j)) + src = gr.vector_source_c(src_data) + op = filter.adaptive_fir_ccc("test", 1, 20*[0.5+1j, 0.5+1j]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + + def test_adaptive_fir_filter_ccc_002(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((-0.5+1.5j), (-5.5+16.5j), (-10.5+31.5j), + (-15.5+46.5j), (-20.5+61.5j), (-25.5+76.5j), + (-30.5+91.5j), (-35.5+106.5j), (-40.5+121.5j), + (-45.5+136.5j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j)) + src = gr.vector_source_c(src_data) + op = filter.adaptive_fir_ccc("test", 4, 20*[0.5+1j, 0.5+1j]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_adaptive_filter, "test_adaptive_filter.xml") + diff --git a/gr-filter/python/qa_channel_model.py b/gr-filter/python/qa_channel_model.py new file mode 100755 index 0000000000..7f1c61b4e3 --- /dev/null +++ b/gr-filter/python/qa_channel_model.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_channel_model(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + N = 1000 # number of samples to use + fs = 1000 # baseband sampling rate + freq = 100 + + signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1) + head = gr.head(gr.sizeof_gr_complex, N) + op = filter.channel_model(0.0, 0.0, 1.0, [1,], 0) + snk = gr.vector_sink_c() + snk1 = gr.vector_sink_c() + + op.set_noise_voltage(0.0) + op.set_frequency_offset(0.0) + op.set_taps([1,]) + op.set_timing_offset(1.0) + + self.tb.connect(signal, head, op, snk) + self.tb.connect(op, snk1) + self.tb.run() + + dst_data = snk.data() + exp_data = snk1.data() + self.assertComplexTuplesAlmostEqual(exp_data, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_channel_model, "test_channel_model.xml") diff --git a/gr-filter/python/qa_dc_blocker.py b/gr-filter/python/qa_dc_blocker.py new file mode 100755 index 0000000000..b9df06b453 --- /dev/null +++ b/gr-filter/python/qa_dc_blocker.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# +# Copyright 2011,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter + +class test_dc_blocker(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + ''' Test impulse response - long form, cc ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.02072429656982422+0j), (-0.02081298828125+0j), + (0.979156494140625+0j), (-0.02081298828125+0j), + (-0.02072429656982422+0j)) + + src = gr.vector_source_c(src_data) + op = filter.dc_blocker_cc(32, True) + dst = gr.vector_sink_c() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around 2D-2 + result_data = dst.data()[60:65] + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + ''' Test impulse response - short form, cc ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.029296875+0j), (-0.0302734375+0j), + (0.96875+0j), (-0.0302734375+0j), + (-0.029296875+0j)) + + src = gr.vector_source_c(src_data) + op = filter.dc_blocker_cc(32, False) + dst = gr.vector_sink_c() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around D-1 + result_data = dst.data()[29:34] + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + + def test_003(self): + ''' Test impulse response - long form, ff ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.02072429656982422), (-0.02081298828125), + (0.979156494140625), (-0.02081298828125), + (-0.02072429656982422)) + + src = gr.vector_source_f(src_data) + op = filter.dc_blocker_ff(32, True) + dst = gr.vector_sink_f() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around 2D-2 + result_data = dst.data()[60:65] + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_004(self): + ''' Test impulse response - short form, ff ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.029296875), (-0.0302734375), + (0.96875), (-0.0302734375), + (-0.029296875)) + + src = gr.vector_source_f(src_data) + op = filter.dc_blocker_ff(32, False) + dst = gr.vector_sink_f() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around D-1 + result_data = dst.data()[29:34] + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_dc_blocker, "test_dc_blocker.xml") + diff --git a/gr-filter/python/qa_fft_filter.py b/gr-filter/python/qa_fft_filter.py new file mode 100755 index 0000000000..cb5416373f --- /dev/null +++ b/gr-filter/python/qa_fft_filter.py @@ -0,0 +1,380 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import sys +import random + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(2*random.random()-1, + 2*random.random()-1)) + return tuple(result) + +def make_random_float_tuple(L): + result = [] + for x in range(L): + result.append(float(int(2*random.random()-1))) + return tuple(result) + + +def reference_filter_ccc(dec, taps, input): + """ + compute result using conventional fir filter + """ + tb = gr.top_block() + #src = gr.vector_source_c(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_c(input) + op = filter.fir_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + return dst.data() + +def reference_filter_fff(dec, taps, input): + """ + compute result using conventional fir filter + """ + tb = gr.top_block() + #src = gr.vector_source_f(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_f(input) + op = filter.fir_filter_fff(dec, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + return dst.data() + + +def print_complex(x): + for i in x: + i = complex(i) + sys.stdout.write("(%6.3f,%6.3fj), " % (i.real, i.imag)) + sys.stdout.write('\n') + + +class test_fft_filter(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def assert_fft_ok2(self, expected_result, result_data): + expected_result = expected_result[:len(result_data)] + self.assertComplexTuplesAlmostEqual2 (expected_result, result_data, + abs_eps=1e-9, rel_eps=4e-4) + + def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4): + expected_result = expected_result[:len(result_data)] + self.assertFloatTuplesAlmostEqual2 (expected_result, result_data, + abs_eps, rel_eps) + + def test_ccc_001(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = filter.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_ccc_002(self): + # Test nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = filter.fft_filter_ccc(1, taps, nthreads) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_ccc_003(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = filter.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_ccc_004(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(1, taps, src_data) + + src = gr.vector_source_c(src_data) + op = filter.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + del tb + self.assert_fft_ok2(expected_result, result_data) + + def test_ccc_005(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = filter.fft_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + del tb + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + def test_ccc_006(self): + # Test decimating with nthreads=2 + random.seed(0) + nthreads = 2 + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = filter.fft_filter_ccc(dec, taps, nthreads) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + del tb + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + # ---------------------------------------------------------------- + # test _fff version + # ---------------------------------------------------------------- + + def test_fff_001(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_fff_002(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def test_fff_003(self): + # Test 02 with nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(1, taps, nthreads) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def xtest_fff_004(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4096 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + #print "src_len =", src_len, " ntaps =", ntaps + try: + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=1.0) + except: + expected = open('expected', 'w') + for x in expected_result: + expected.write(`x` + '\n') + actual = open('actual', 'w') + for x in result_data: + actual.write(`x` + '\n') + raise + + def xtest_fff_005(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0) + + def xtest_fff_006(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(dec, taps) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + + def xtest_fff_007(self): + # test decimation with nthreads + random.seed(0) + nthreads = 2 + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = filter.fft_filter_fff(dec, taps, nthreads) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + + def test_fff_get0(self): + random.seed(0) + for i in xrange(25): + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + + op = filter.fft_filter_fff(1, taps) + result_data = op.taps() + #print result_data + + self.assertEqual(taps, result_data) + + def test_ccc_get0(self): + random.seed(0) + for i in xrange(25): + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + + op = filter.fft_filter_ccc(1, taps) + result_data = op.taps() + #print result_data + + self.assertComplexTuplesAlmostEqual(taps, result_data, 4) + + +if __name__ == '__main__': + gr_unittest.run(test_fft_filter, "test_fft_filter.xml") + diff --git a/gr-filter/python/qa_filter_delay_fc.py b/gr-filter/python/qa_filter_delay_fc.py new file mode 100755 index 0000000000..57b063e7b5 --- /dev/null +++ b/gr-filter/python/qa_filter_delay_fc.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_filter_delay_fc(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_filter_delay_one_input(self): + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + tb = self.tb + + sampling_freq = 100 + + ntaps = 51 + src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c() + + # calculate taps + taps = filter.firdes_hilbert(ntaps) + hd = filter.filter_delay_fc(taps) + + tb.connect(src1, head) + tb.connect(head, hd) + tb.connect(hd,dst2) + + tb.run() + + # get output + result_data = dst2.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 5) + + def test_002_filter_delay_two_inputs(self): + + # giving the same signal to both the inputs should fetch the same results + # as above + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + tb = self.tb + + sampling_freq = 100 + ntaps = 51 + src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c() + + + # calculate taps + taps = filter.firdes_hilbert(ntaps) + hd = filter.filter_delay_fc(taps) + + tb.connect(src1, head) + tb.connect(head, (hd,0)) + tb.connect(head, (hd,1)) + tb.connect(hd,dst2) + tb.run() + + # get output + result_data = dst2.data() + + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 5) + + + def test_003_filter_delay_two_inputs(self): + + # give two different inputs + + # expected result + expected_result = ( -0.0020331963896751404j, + -0.0016448829555884004j, + -0.0032375147566199303j, + -0.0014826074475422502j, + -0.0033034090884029865j, + -0.00051144487224519253j, + -0.0043686260469257832j, + -0.0010198024101555347j, + -0.0082517862319946289j, + -0.003456643782556057j, + -0.014193611219525337j, + -0.005875137634575367j, + -0.020293503999710083j, + -0.0067503536120057106j, + -0.026798896491527557j, + -0.0073488112539052963j, + -0.037041611969470978j, + -0.010557252913713455j, + -0.055669989436864853j, + -0.018332764506340027j, + -0.089904911816120148j, + -0.033361352980136871j, + -0.16902604699134827j, + -0.074318811297416687j, + -0.58429563045501709j, + (7.2191945754696007e-09 -0.35892376303672791j), + (0.58778399229049683 +0.63660913705825806j), + (0.95105588436126709 +0.87681591510772705j), + (0.95105588436126709 +0.98705857992172241j), + (0.5877838134765625 +0.55447429418563843j), + (5.8516356205018383e-09 +0.026006083935499191j), + (-0.5877840518951416 -0.60616838932037354j), + (-0.95105588436126709 -0.9311758279800415j), + (-0.95105588436126709 -0.96169203519821167j), + (-0.5877838134765625 -0.57292771339416504j), + (-8.7774534307527574e-09 -0.0073488391935825348j), + (0.58778399229049683 +0.59720659255981445j), + (0.95105588436126709 +0.94438445568084717j), + (0.95105588436126709 +0.95582199096679688j), + (0.5877838134765625 +0.58196049928665161j), + (1.4629089051254596e-08 +0.0026587247848510742j), + (-0.5877840518951416 -0.59129220247268677j), + (-0.95105588436126709 -0.94841635227203369j), + (-0.95105588436126709 -0.95215457677841187j), + (-0.5877838134765625 -0.58535969257354736j), + (-1.7554906861505515e-08 -0.00051158666610717773j), + (0.58778399229049683 +0.58867418766021729j), + (0.95105582475662231 +0.94965213537216187j), + (0.95105588436126709 +0.95050644874572754j), + (0.5877838134765625 +0.58619076013565063j), + (2.3406542482007353e-08 +1.1920928955078125e-07j), + (-0.5877840518951416 -0.58783555030822754j), + (-0.95105588436126709 -0.95113480091094971j), + (-0.95105588436126709 -0.95113474130630493j), + (-0.5877838134765625 -0.58783555030822754j), + (-2.6332360292258272e-08 -8.1956386566162109e-08j), + (0.58778399229049683 +0.58783555030822754j), + (0.95105582475662231 +0.95113474130630493j), + (0.95105588436126709 +0.95113474130630493j), + (0.5877838134765625 +0.58783560991287231j), + (3.218399768911695e-08 +1.1920928955078125e-07j)) + + tb = self.tb + + sampling_freq = 100 + ntaps = 51 + + src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE,sampling_freq * 0.10, 1.0) + src2 = gr.sig_source_f(sampling_freq, gr.GR_COS_WAVE,sampling_freq * 0.10, 1.0) + + head1 = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10)) + head2 = gr.head(gr.sizeof_float, int(ntaps + sampling_freq * 0.10)) + + taps = filter.firdes_hilbert(ntaps) + hd = filter.filter_delay_fc(taps) + + dst2 = gr.vector_sink_c() + + tb.connect(src1, head1) + tb.connect(src2, head2) + + tb.connect(head1, (hd,0)) + tb.connect(head2, (hd,1)) + tb.connect(hd, dst2) + + tb.run() + + # get output + result_data = dst2.data() + + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 5) + + +if __name__ == '__main__': + gr_unittest.run(test_filter_delay_fc, "test_filter_delay_fc.xml") diff --git a/gr-filter/python/qa_fir_filter.py b/gr-filter/python/qa_fir_filter.py new file mode 100755 index 0000000000..2a61498a26 --- /dev/null +++ b/gr-filter/python/qa_fir_filter.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python +# +# Copyright 2008,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter + +class test_filter(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_fir_filter_fff_001(self): + src_data = 40*[1, 2, 3, 4] + expected_data = (0.5, 1.5, 3.0, 5.0, 5.5, 6.5, 8.0, 10.0, + 10.5, 11.5, 13.0, 15.0, 15.5, 16.5, 18.0, + 20.0, 20.5, 21.5, 23.0, 25.0, 25.5, 26.5, + 28.0, 30.0, 30.5, 31.5, 33.0, 35.0, 35.5, + 36.5, 38.0, 40.0, 40.5, 41.5, 43.0, 45.0, + 45.5, 46.5, 48.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0) + src = gr.vector_source_f(src_data) + op = filter.fir_filter_fff(1, 20*[0.5, 0.5]) + dst = gr.vector_sink_f() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5) + + def test_fir_filter_fff_002(self): + src_data = 40*[1, 2, 3, 4] + expected_data = (0.5, 5.5, 10.5, 15.5, 20.5, 25.5, 30.5, 35.5, + 40.5, 45.5, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, + 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0) + src = gr.vector_source_f(src_data) + op = filter.fir_filter_fff(4, 20*[0.5, 0.5]) + dst = gr.vector_sink_f() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_data, result_data, 5) + + def test_fir_filter_ccf_001(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((0.5+0.5j), (1.5+1.5j), (3+3j), (5+5j), (5.5+5.5j), + (6.5+6.5j), (8+8j), (10+10j), (10.5+10.5j), (11.5+11.5j), + (13+13j), (15+15j), (15.5+15.5j), (16.5+16.5j), (18+18j), + (20+20j), (20.5+20.5j), (21.5+21.5j), (23+23j), (25+25j), + (25.5+25.5j), (26.5+26.5j), (28+28j), (30+30j), (30.5+30.5j), + (31.5+31.5j), (33+33j), (35+35j), (35.5+35.5j), (36.5+36.5j), + (38+38j), (40+40j), (40.5+40.5j), (41.5+41.5j), (43+43j), + (45+45j), (45.5+45.5j), (46.5+46.5j), (48+48j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j)) + + src = gr.vector_source_c(src_data) + op = filter.fir_filter_ccf(1, 20*[0.5, 0.5]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + def test_fir_filter_ccf_002(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((0.5+0.5j), (5.5+5.5j), (10.5+10.5j), (15.5+15.5j), + (20.5+20.5j), (25.5+25.5j), (30.5+30.5j), (35.5+35.5j), + (40.5+40.5j), (45.5+45.5j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j), (50+50j), + (50+50j), (50+50j), (50+50j), (50+50j)) + + src = gr.vector_source_c(src_data) + op = filter.fir_filter_ccf(4, 20*[0.5, 0.5]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + def test_fir_filter_ccc_001(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((-0.5+1.5j), (-1.5+4.5j), (-3+9j), (-5+15j), + (-5.5+16.5j), (-6.5+19.5j), (-8+24j), (-10+30j), + (-10.5+31.5j), (-11.5+34.5j), (-13+39j), (-15+45j), + (-15.5+46.5j), (-16.5+49.5j), (-18+54j), (-20+60j), + (-20.5+61.5j), (-21.5+64.5j), (-23+69j), (-25+75j), + (-25.5+76.5j), (-26.5+79.5j), (-28+84j), (-30+90j), + (-30.5+91.5j), (-31.5+94.5j), (-33+99j), (-35+105j), + (-35.5+106.5j), (-36.5+109.5j), (-38+114j), (-40+120j), + (-40.5+121.5j), (-41.5+124.5j), (-43+129j), (-45+135j), + (-45.5+136.5j), (-46.5+139.5j), (-48+144j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), (-50+150j)) + src = gr.vector_source_c(src_data) + op = filter.fir_filter_ccc(1, 20*[0.5+1j, 0.5+1j]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + + def test_fir_filter_ccc_002(self): + src_data = 10*[1+1j, 2+2j, 3+3j, 4+4j] + + # results derived from original gr.fir_filter_ccc + expected_data = ((7.537424837948042e-20+7.537424837948042e-20j), (9.131923434324563e-05+9.131923434324563e-05j), (0.0003317668742965907+0.0003317668742965907j), (0.0007230418268591166+0.0007230418268591166j), (0.0012087896466255188+0.0012087896466255188j), (0.0013292605290189385+0.0013292605290189385j), (0.001120875240303576+0.001120875240303576j), (0.000744672492146492+0.000744672492146492j), (0.000429437990533188+0.000429437990533188j), (2.283908543176949e-05+2.283908543176949e-05j), (-0.0002245186478830874-0.0002245186478830874j), (-0.0001157080550910905-0.0001157080550910905j), (0.00041409023106098175+0.00041409023106098175j), (0.0009017843985930085+0.0009017843985930085j), (0.0012520025484263897+0.0012520025484263897j), (0.0014116164529696107+0.0014116164529696107j), (0.001393353333696723+0.001393353333696723j), (0.000912194955162704+0.000912194955162704j), (0.00022649182938039303+0.00022649182938039303j), (-0.00031363096786662936-0.00031363096786662936j), (-0.0003966730728279799-0.0003966730728279799j), (-0.00023757052258588374-0.00023757052258588374j), (0.00021952332463115454+0.00021952332463115454j), (0.0009092430118471384+0.0009092430118471384j), (0.001662317430600524+0.001662317430600524j), (0.0019024648936465383+0.0019024648936465383j), (0.0015955769922584295+0.0015955769922584295j), (0.0009144138311967254+0.0009144138311967254j), (0.0001872836146503687+0.0001872836146503687j), (-0.000581968342885375-0.000581968342885375j), (-0.0009886166080832481-0.0009886166080832481j), (-0.0007480768254026771-0.0007480768254026771j), (0.00018211957649327815+0.00018211957649327815j), (0.0012042406015098095+0.0012042406015098095j), (0.0020200139842927456+0.0020200139842927456j), (0.0023816542234271765+0.0023816542234271765j), (0.002195809967815876+0.002195809967815876j), (0.0012113333214074373+0.0012113333214074373j), (-0.00014088614261709154-0.00014088614261709154j), (-0.0012574587017297745-0.0012574587017297745j)) + + taps = filter.firdes.low_pass(1, 1, 0.1, 0.01) + src = gr.vector_source_c(src_data) + op = filter.fir_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + def test_fir_filter_ccc_003(self): + src_data = 40*[1+1j, 2+2j, 3+3j, 4+4j] + expected_data = ((-0.5+1.5j), (-5.5+16.5j), (-10.5+31.5j), + (-15.5+46.5j), (-20.5+61.5j), (-25.5+76.5j), + (-30.5+91.5j), (-35.5+106.5j), (-40.5+121.5j), + (-45.5+136.5j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j), (-50+150j), + (-50+150j), (-50+150j), (-50+150j)) + src = gr.vector_source_c(src_data) + op = filter.fir_filter_ccc(4, 20*[0.5+1j, 0.5+1j]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + + def test_fir_filter_scc_001(self): + src_data = 40*[1, 2, 3, 4] + expected_data = ((0.5+1j), (1.5+3j), (3+6j), (5+10j), (5.5+11j), + (6.5+13j), (8+16j), (10+20j), (10.5+21j), (11.5+23j), + (13+26j), (15+30j), (15.5+31j), (16.5+33j), (18+36j), + (20+40j), (20.5+41j), (21.5+43j), (23+46j), (25+50j), + (25.5+51j), (26.5+53j), (28+56j), (30+60j), (30.5+61j), + (31.5+63j), (33+66j), (35+70j), (35.5+71j), (36.5+73j), + (38+76j), (40+80j), (40.5+81j), (41.5+83j), (43+86j), + (45+90j), (45.5+91j), (46.5+93j), (48+96j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j)) + src = gr.vector_source_s(src_data) + op = filter.fir_filter_scc(1, 20*[0.5+1j, 0.5+1j]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + + def test_fir_filter_scc_002(self): + src_data = 40*[1, 2, 3, 4] + expected_data = ((0.5+1j), (5.5+11j), (10.5+21j), (15.5+31j), (20.5+41j), + (25.5+51j), (30.5+61j), (35.5+71j), (40.5+81j), (45.5+91j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j), + (50+100j), (50+100j), (50+100j), (50+100j), (50+100j)) + src = gr.vector_source_s(src_data) + op = filter.fir_filter_scc(4, 20*[0.5+1j, 0.5+1j]) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + def test_fir_filter_fsf_001(self): + src_data = 40*[1, 2, 3, 4] + expected_data =(0, 1, 3, 5, 5, 6, 8, 10, 10, 11, 13, 15, 15, 16, 18, 20, 20, + 21, 23, 25, 25, 26, 28, 30, 30, 31, 33, 35, 35, 36, 38, 40, 40, + 41, 43, 45, 45, 46, 48, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50) + src = gr.vector_source_f(src_data) + op = filter.fir_filter_fsf(1, 20*[0.5, 0.5]) + dst = gr.vector_sink_s() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + + + def test_fir_filter_fsf_002(self): + src_data = 40*[1, 2, 3, 4] + expected_data = (0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 50, 50, 50) + src = gr.vector_source_f(src_data) + op = filter.fir_filter_fsf(4, 20*[0.5, 0.5]) + dst = gr.vector_sink_s() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_filter, "test_filter.xml") + diff --git a/gr-filter/python/qa_firdes.py b/gr-filter/python/qa_firdes.py new file mode 100755 index 0000000000..cfd10435f5 --- /dev/null +++ b/gr-filter/python/qa_firdes.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import sys + +class test_firdes(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_low_pass(self): + known_taps = (0.0030193300917744637, -0.004960992839187384, + 0.006678304169327021, -1.132049690556083e-17, + -0.0251916591078043, 0.07206480950117111, + -0.13062666356563568, 0.18007083237171173, + 0.7978920936584473, 0.18007083237171173, + -0.13062666356563568, 0.07206480950117111, + -0.0251916591078043, -1.132049690556083e-17, + 0.006678304169327021, -0.004960992839187384, + 0.0030193300917744637) + new_taps = filter.firdes.low_pass(1, 1, 0.4, 0.2) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_low_pass_2(self): + known_taps = (0.0024871660862118006, -4.403502608370943e-18, + -0.014456653036177158, 0.0543283149600029, + -0.116202212870121, 0.17504146695137024, + 0.7976038455963135, 0.17504146695137024, + -0.116202212870121, 0.0543283149600029, + -0.014456653036177158, -4.403502608370943e-18, + 0.0024871660862118006) + new_taps = filter.firdes.low_pass_2(1, 1, 0.4, 0.2, 60) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_high_pass(self): + known_taps = (-0.003062003292143345, 0.005031108390539885, + -0.0067726909182965755, 1.1480492661182674e-17, + 0.025547700002789497, -0.0730833187699318, + 0.13247284293174744, -0.18261581659317017, + 0.20229223370552063, -0.18261581659317017, + 0.13247284293174744, -0.0730833187699318, + 0.025547700002789497, 1.1480492661182674e-17, + -0.0067726909182965755, 0.005031108390539885, + -0.003062003292143345) + new_taps = filter.firdes.high_pass(1, 1, 0.4, 0.2) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_high_pass_2(self): + known_taps = (-0.0027197482995688915, 4.815287179370254e-18, + 0.01580853760242462, -0.05940871313214302, + 0.1270686239004135, -0.1914101094007492, + 0.21804752945899963, -0.1914101094007492, + 0.1270686239004135, -0.05940871313214302, + 0.01580853760242462, 4.815287179370254e-18, + -0.0027197482995688915) + new_taps = filter.firdes.high_pass_2(1, 1, 0.4, 0.2, 60) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_band_pass(self): + known_taps = (0.004961997736245394, -0.008152946829795837, + -0.004192151129245758, -5.749020235348687e-18, + 0.01581347920000553, 0.11843203753232956, + -0.21467317640781403, -0.11303528398275375, + 0.40520283579826355, -0.11303528398275375, + -0.21467317640781403, 0.11843203753232956, + 0.01581347920000553, -5.749020235348687e-18, + -0.004192151129245758, -0.008152946829795837, + 0.004961997736245394) + new_taps = filter.firdes.band_pass(1, 1, 0.2, 0.4, 0.2) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_band_pass_2(self): + known_taps = (-0.001676854444667697, -2.4018533253972557e-18, + 0.009746716357767582, 0.09589414298534393, + -0.20510689914226532, -0.11801345646381378, + 0.4350462853908539, -0.11801345646381378, + -0.20510689914226532, 0.09589414298534393, + 0.009746716357767582, -2.4018533253972557e-18, + -0.001676854444667697) + new_taps = filter.firdes.band_pass_2(1, 1, 0.2, 0.4, 0.2, 60) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_complex_band_pass(self): + known_taps = ((0.0024772135075181723+0.0017997993854805827j), + (-0.004070250317454338+0.002957213670015335j), + (-0.0020928815938532352-0.006441210396587849j), + (-2.8701231652956686e-18+2.805614574993832e-24j), + (0.007894645445048809-0.024297315627336502j), + (0.05912570655345917+0.04295721650123596j), + (-0.10717268288135529+0.07786571979522705j), + (-0.0564316064119339-0.17367789149284363j), + (0.20229223370552063-2.4115112751132983e-07j), + (-0.05643119290471077+0.17367802560329437j), + (-0.10717286914587021-0.07786546647548676j), + (0.05912560224533081-0.0429573580622673j), + (0.007894691079854965+0.024297300726175308j), + (-2.8701231652956686e-18+2.6687109203363464e-24j), + (-0.0020928694866597652+0.006441214121878147j), + (-0.004070255905389786-0.0029572059866040945j), + (0.0024772100150585175-0.0017998040420934558j)) + new_taps = filter.firdes.complex_band_pass(1, 1, 0.2, 0.4, 0.2) + self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_complex_band_pass_2(self): + known_taps = ((-0.0008404505206272006-0.0025866336654871702j), + (-1.2038217948425635e-18+1.1767648157397848e-24j), + (0.0048850891180336475-0.015034818090498447j), + (0.048062704503536224+0.03491950035095215j), + (-0.10280057787895203+0.07468919456005096j), + (-0.05914920195937157-0.18204176425933838j), + (0.21804752945899963-2.5993290364567656e-07j), + (-0.059148769825696945+0.18204189836978912j), + (-0.10280075669288635-0.07468894869089127j), + (0.04806262254714966-0.0349196158349514j), + (0.004885117989033461+0.015034808777272701j), + (-1.2038217948425635e-18+1.1193430388030685e-24j), + (-0.000840445572976023+0.002586635295301676j)) + new_taps = filter.firdes.complex_band_pass_2(1, 1, 0.2, 0.4, 0.2, 60) + self.assertComplexTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_band_reject(self): + known_taps = (-0.004915320314466953, 0.008076251484453678, + 0.00415271520614624, 5.694938753309664e-18, + -0.01566472090780735, -0.11731793731451035, + 0.2126537412405014, 0.11197195947170258, + 0.6020866632461548, 0.11197195947170258, + 0.2126537412405014, -0.11731793731451035, + -0.01566472090780735, 5.694938753309664e-18, + 0.00415271520614624, 0.008076251484453678, + -0.004915320314466953) + new_taps = filter.firdes.band_reject(1, 1, 0.2, 0.4, 0.2) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_band_reject_2(self): + known_taps = (0.0015371545450761914, 2.201753372137003e-18, + -0.00893471110612154, -0.08790513873100281, + 0.1880193054676056, 0.1081816703081131, + 0.5982034206390381, 0.1081816703081131, + 0.1880193054676056, -0.08790513873100281, + -0.00893471110612154, 2.201753372137003e-18, + 0.0015371545450761914) + new_taps = filter.firdes.band_reject_2(1, 1, 0.2, 0.4, 0.2, 60) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_hilbert(self): + known_taps = (-0.010056184604763985, 0.0, + -0.08335155993700027, 0.0, + -0.5732954144477844, 0.0, + 0.5732954144477844, 0.0, + 0.08335155993700027, 0.0, + 0.010056184604763985) + new_taps = filter.firdes.hilbert(11) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_root_raised_cosine(self): + known_taps = (-0.04609205573797226, -0.02069387212395668, + 0.050548505038022995, 0.14850808680057526, + 0.23387153446674347, 0.2677156329154968, + 0.23387153446674347, 0.14850808680057526, + 0.050548505038022995, -0.02069387212395668, + -0.04609205573797226) + new_taps = filter.firdes.root_raised_cosine(1, 4, 1, 0.35, 11) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + + def test_gaussian(self): + known_taps = (0.0003600157215259969, 0.0031858310103416443, + 0.0182281993329525, 0.06743486225605011, + 0.16130395233631134, 0.24947398900985718, + 0.24947398900985718, 0.16130395233631134, + 0.06743486225605011, 0.0182281993329525, + 0.0031858310103416443, 0.0003600157215259969, + 2.630509879963938e-05) + new_taps = filter.firdes.gaussian(1, 4, 0.35, 13) + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + +if __name__ == '__main__': + gr_unittest.run(test_firdes, "test_firdes.xml") + diff --git a/gr-filter/python/qa_fractional_interpolator.py b/gr-filter/python/qa_fractional_interpolator.py new file mode 100755 index 0000000000..9e0f685d80 --- /dev/null +++ b/gr-filter/python/qa_fractional_interpolator.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# Copyright 2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_fractional_resampler(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_ff(self): + N = 10000 # number of samples to use + fs = 1000 # baseband sampling rate + rrate = 1.123 # resampling rate + + freq = 10 + signal = gr.sig_source_f(fs, gr.GR_SIN_WAVE, freq, 1) + head = gr.head(gr.sizeof_float, N) + op = filter.fractional_interpolator_ff(0, rrate) + snk = gr.vector_sink_f() + + self.tb.connect(signal, head, op, snk) + self.tb.run() + + Ntest = 5000 + L = len(snk.data()) + t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + + phase = 0.1884 + expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t) + + dst_data = snk.data() + + self.assertFloatTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3) + + + def test_002_cc(self): + N = 10000 # number of samples to use + fs = 1000 # baseband sampling rate + rrate = 1.123 # resampling rate + + freq = 10 + signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1) + head = gr.head(gr.sizeof_gr_complex, N) + op = filter.fractional_interpolator_cc(0.0, rrate) + snk = gr.vector_sink_c() + + self.tb.connect(signal, head, op, snk) + self.tb.run() + + Ntest = 5000 + L = len(snk.data()) + t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + + phase = 0.1884 + expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase), t) + + dst_data = snk.data() + + self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3) + + +if __name__ == '__main__': + gr_unittest.run(test_fractional_resampler, "test_fractional_resampler.xml") diff --git a/gr-filter/python/qa_freq_xlating_fir_filter.py b/gr-filter/python/qa_freq_xlating_fir_filter.py new file mode 100755 index 0000000000..ee38eb7dff --- /dev/null +++ b/gr-filter/python/qa_freq_xlating_fir_filter.py @@ -0,0 +1,445 @@ +#!/usr/bin/env python +# +# Copyright 2008,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import cmath, math + +class test_freq_xlating_filter(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def generate_ccf_source(self): + self.fs = fs = 1 + self.fc = fc = 0.3 + self.bw = bw = 0.1 + self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) + times = xrange(100) + self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times) + + def generate_ccc_source(self): + self.fs = fs = 1 + self.fc = fc = 0.3 + self.bw = bw = 0.1 + self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) + times = xrange(100) + self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times) + + def generate_fcf_source(self): + self.fs = fs = 1 + self.fc = fc = 0.3 + self.bw = bw = 0.1 + self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) + times = xrange(100) + self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times) + + def generate_fcc_source(self): + self.fs = fs = 1 + self.fc = fc = 0.3 + self.bw = bw = 0.1 + self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) + times = xrange(100) + self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times) + + def generate_scf_source(self): + self.fs = fs = 1 + self.fc = fc = 0.3 + self.bw = bw = 0.1 + self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) + times = xrange(100) + self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times) + + def generate_scc_source(self): + self.fs = fs = 1 + self.fc = fc = 0.3 + self.bw = bw = 0.1 + self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) + times = xrange(100) + self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times) + + + def test_fir_filter_ccf_001(self): + self.generate_ccf_source() + expected_data = ((0.001697700354270637+0.004312471952289343j), + (0.003520616563037038-0.003014103975147009j), + (0.004252811893820763-0.008337559178471565j), + (0.0030743128154426813-0.010262271389365196j), + (0.0007344777695834637-0.007861139252781868j), + (-0.0011067686136811972-0.0028924935031682253j), + (-0.002371778478845954+0.0019914964213967323j), + (-0.003023319412022829+0.005717850290238857j), + (-0.0021738125942647457+0.007211698684841394j), + (-0.0004628606839105487+0.005501383915543556j), + (0.0007428556564264+0.0019867848604917526j), + (0.001634795218706131-0.0013514887541532516j), + (0.002205110155045986-0.00402155052870512j), + (0.0015480631263926625-0.005179159343242645j), + (0.00026722141774371266-0.003887997241690755j), + (-0.0004911854630336165-0.0013578246580436826j), + (-0.0011226939968764782+0.0009080552263185382j), + (-0.0016229727771133184+0.0028335191309452057j), + (-0.0010890064295381308+0.0037298379465937614j), + (-0.00012392725329846144+0.0027196139562875032j)) + src = gr.vector_source_c(self.src_data) + op = filter.freq_xlating_fir_filter_ccf(1, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_ccf_002(self): + self.generate_ccf_source() + expected_data = ((6.419439159799367e-05-0.0006292851758189499j), + (-0.00037074743886478245+0.0013245552545413375j), + (0.0006853155209682882-0.0023769831750541925j), + (-0.001427714480087161+0.002608160488307476j), + (0.0015907397028058767-0.000811046629678458j), + (-0.0004226673918310553-0.0024389736354351044j), + (-0.0013841050677001476+0.006231029983609915j), + (0.0035029184073209763-0.009738259017467499j), + (-0.005924836732447147+0.010320881381630898j), + (0.006831614300608635-0.003950652200728655j), + (-0.0021247887052595615-0.015604906715452671j), + (-0.04283163696527481+0.09995654970407486j), + (-0.01391829177737236+0.07924056798219681j), + (0.010886997915804386-0.02463012933731079j), + (-0.0056075905449688435+0.004998659715056419j), + (0.0016976913902908564+0.004312459379434586j), + (0.0007344821933656931-0.007861112244427204j), + (-0.002173811662942171+0.007211671676486731j), + (0.0022051059640944004-0.00402153329923749j), + (-0.0011226903880015016+0.0009080505697056651j)) + src = gr.vector_source_c(self.src_data) + op = filter.freq_xlating_fir_filter_ccf(4, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_ccc_001(self): + self.generate_ccc_source() + expected_data = ((0.0036842757836-0.0114002721384j), + (0.00324621866457-0.0108166672289j), + (0.00206564785913-0.00923090614378j), + (0.00109899020754-0.00656201224774j), + (0.000506619049702-0.00402844604105j), + (-0.000523390364833-0.00166808743961j), + (-0.00140534969978+0.00103991874494j), + (-0.00154365820345+0.00315759982914j), + (-0.00180402118713+0.00427215453237j), + (-0.00216706306674+0.00524478312582j), + (-0.00178848754149+0.0057489364408j), + (-0.00129876169376+0.00512680830434j), + (-0.00122803379782+0.00427244976163j), + (-0.000722666736692+0.00351428100839j), + (5.53092104383e-05+0.00207865727134j), + (0.000227351076319+0.000517217209563j), + (0.000414477253798-0.000383921898901j), + (0.000998671515845-0.00135387131013j), + (0.00104933069088-0.00243046949618j), + (0.000765930046327-0.0026717747096j)) + src = gr.vector_source_c(self.src_data) + op = filter.freq_xlating_fir_filter_ccc(1, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_ccc_002(self): + self.generate_ccc_source() + expected_data = ((-0.000650451984257+0.00120697380044j), + (-9.59713361226e-05+0.00102412770502j), + (0.000958710326813-0.00145424995571j), + (0.000901343999431-0.00290832063183j), + (-0.000822560978122+0.000296717538731j), + (-0.00211223773658+0.00519825471565j), + (-0.00037001183955+0.00358242215589j), + (0.00327983591706-0.00616005761549j), + (0.00356886954978-0.0117237549275j), + (-0.00328874029219+0.00182871113066j), + (-0.0139285130426+0.0320657044649j), + (-0.0198133718222+0.0562113076448j), + (-0.0157803222537+0.0530290603638j), + (-0.00550725404173+0.0255754813552j), + (0.00252919178456-0.00232240976766j), + (0.00368427345529-0.0114002330229j), + (0.000506620621309-0.00402843113989j), + (-0.00180401885882+0.00427213776857j), + (-0.00122803344857+0.00427243299782j), + (0.000414476031438-0.000383919978049j)) + src = gr.vector_source_c(self.src_data) + op = filter.freq_xlating_fir_filter_ccc(4, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_fcf_001(self): + self.generate_fcf_source() + expected_data = ((0.000247188087087-0.000157509770361j), + (-0.000155229790835-0.000246197130764j), + (-0.000264906557277+0.000174603672349j), + (6.99016964063e-05+0.000174961372977j), + (-5.48477692064e-05-0.0001131295503j), + (-0.000237467131228+0.000118011368613j), + (0.000136614587973+0.000229531884543j), + (0.000229347482673-0.000166581812664j), + (-0.000106010869786-0.000150042149471j), + (2.92293734674e-05+0.000142060467624j), + (0.000228707227507-9.30760797928e-05j), + (-0.000124306126963-0.000216641055886j), + (-0.000204823678359+0.00016052465071j), + (0.00012825592421+0.000133123627165j), + (-1.18284006021e-05-0.000159015646204j), + (-0.000219973371713+7.5438656495e-05j), + (0.000114713984658+0.000205190401175j), + (0.000185727752978-0.000154630601173j), + (-0.000141745767905-0.000120098840853j), + (-3.9850056055e-07+0.000168364742422j)) + src = gr.vector_source_f(self.src_data) + op = filter.freq_xlating_fir_filter_fcf(1, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_fcf_002(self): + self.generate_fcf_source() + expected_data = ((7.3052920925e-05-3.91741014028e-06j), + (3.11913172482e-05-0.000109872074972j), + (-0.000128646017401-3.49857727997e-05j), + (-5.49546712136e-05+8.96326746442e-05j), + (5.14321582159e-05+9.64698920143e-05j), + (0.000120189361041+2.4231892894e-05j), + (0.000100405508419-0.000223224604269j), + (-0.000274751859251-2.33274622587e-05j), + (1.52600114234e-06+0.000133301247843j), + (3.77224641852e-05+5.29596509296e-05j), + (-3.60160379387e-06+0.000247975171078j), + (0.00113093166146-0.000663110695314j), + (0.00059568521101-0.00099650840275j), + (-0.000475480686873+0.000250602373853j), + (0.000191397906747+0.000271986238658j), + (0.000247183139436-0.000157510468853j), + (-5.48357638763e-05-0.000113135029096j), + (-0.00010601492977-0.00015005269961j), + (-0.000204817260965+0.000160534662427j), + (0.000114742244477+0.000205190313864j)) + src = gr.vector_source_f(self.src_data) + op = filter.freq_xlating_fir_filter_fcf(4, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_fcc_001(self): + self.generate_fcc_source() + expected_data = ((-0.000337088305969+7.46004516259e-05j), + (-5.63409266761e-05+0.000301144464174j), + (9.16960561881e-05-2.89259278361e-05j), + (-0.000231866899412-6.25764005235e-05j), + (-0.000116414688819+0.000258557556663j), + (0.000206079319469+5.05045172758e-05j), + (-3.85114690289e-05-0.00019276549574j), + (-0.000146380873048+0.000112079876999j), + (0.000215423395275+0.000116706331028j), + (0.000136050162837-0.000232611957472j), + (-0.000155499437824-5.41604022146e-05j), + (0.000106907449663+0.00016310159117j), + (0.000224392410018-0.000156331108883j), + (-0.000131131906528-0.000172063446371j), + (-5.92393880652e-05+0.00016801241145j), + (0.000214921761653-5.32235890205e-06j), + (-5.96960526309e-05-0.000211164733628j), + (-0.000193948610104+0.000113364716526j), + (0.000134820176754+0.000142527525895j), + (4.74465123261e-05-0.000175131688593j)) + src = gr.vector_source_f(self.src_data) + op = filter.freq_xlating_fir_filter_fcc(1, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_fcc_002(self): + self.generate_fcc_source() + expected_data = ((-6.94218761055e-05-9.90489479591e-06j), + (-2.56973435171e-05+8.05932795629e-05j), + (7.01698663761e-05+7.36373840482e-05j), + (7.57163215894e-05-4.65324592369e-05j), + (-3.01657128148e-05-0.000122838056996j), + (-9.53659764491e-05-3.73945695173e-05j), + (-2.33501577895e-05+0.000109135726234j), + (6.65136758471e-05+0.000125709688291j), + (3.08501912514e-05-9.16842873266e-06j), + (-2.64703612629e-05-0.000135892929393j), + (0.000136643866426-0.000162003751029j), + (0.000501801609062-0.000185820827028j), + (0.000694551155902-0.000299874518532j), + (0.000424396857852-0.00038379128091j), + (-9.1786707344e-05-0.000242479465669j), + (-0.000337087287335+7.45999423089e-05j), + (-0.000116414521472+0.000258556567132j), + (0.000215422536712+0.000116706112749j), + (0.000224391726078-0.000156330308528j), + (-5.96956087975e-05-0.000211163976928j)) + src = gr.vector_source_f(self.src_data) + op = filter.freq_xlating_fir_filter_fcc(4, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_scf_001(self): + self.generate_scf_source() + expected_data = ((-0.0330070219934+0.101965591311j), + (-0.0484239049256+0.0872343629599j), + (-0.0214109234512+0.102555386722j), + (0.0484058149159+0.0557125210762j), + (0.0574690811336-0.0350844524801j), + (0.0365394353867-0.0802438184619j), + (0.0453781634569-0.130992040038j), + (0.00801951438189-0.214278846979j), + (-0.0770946145058-0.230616629124j), + (-0.105601429939-0.190731987357j), + (-0.105361394584-0.177761554718j), + (-0.131518915296-0.136102750897j), + (-0.103761836886-0.0382263250649j), + (-0.0167790111154+0.0152206514031j), + (0.0277570039034+0.0300403907895j), + (0.056065287441+0.0806603953242j), + (0.118084669113+0.104863211513j), + (0.128281414509+0.0677760615945j), + (0.0748447552323+0.0619902014732j), + (0.0512856245041+0.0775099247694j)) + src = gr.vector_source_s(self.src_data) + op = filter.freq_xlating_fir_filter_scf(1, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_scf_002(self): + self.generate_scf_source() + expected_data = ((0.00824625696987-1.50158575707e-05j), + (0.0020101047121-0.0116540221497j), + (-0.0126378880814-0.00259830290452j), + (-0.00363933457993+0.00837504956871j), + (0.00107023562305+0.00915473792702j), + (0.0169738996774+0.00422182958573j), + (0.00630031805485-0.025423232466j), + (-0.0283014029264+0.00104465708137j), + (0.00890890974551+0.0115978596732j), + (-0.0142687577754+0.00306978379376j), + (0.02845691517+0.0331163145602j), + (0.0538152232766-0.0908300876617j), + (-0.0843691527843-0.0956566259265j), + (0.0476895272732+0.0747984498739j), + (0.0898786485195+0.082478672266j), + (-0.0330070182681+0.101965606213j), + (0.0574697069824-0.0350842289627j), + (-0.0770940706134-0.230615705252j), + (-0.103762261569-0.0382265634835j), + (0.11808334291+0.104863762856j)) + src = gr.vector_source_s(self.src_data) + op = filter.freq_xlating_fir_filter_scf(4, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_scc_001(self): + self.generate_scc_source() + expected_data = ((-0.00775564694777+0.0437113791704j), + (0.0108830630779+0.0433648750186j), + (0.015553932637-0.0133284125477j), + (-0.0264905355871-0.0403266139328j), + (-0.0243480335921-0.03030154109j), + (-0.000327925226884-0.069333948195j), + (-0.0306392069906-0.107313856483j), + (-0.0452371090651-0.0854917764664j), + (-0.0108894333243-0.0875641107559j), + (-0.0182112380862-0.118961036205j), + (-0.0447825863957-0.0922874584794j), + (-0.0147479763255-0.0572904124856j), + (0.00204290449619-0.0721436738968j), + (-0.027713002637-0.0548989400268j), + (-0.0149045493454-0.00210141134448j), + (0.0176361314952-0.00149522523861j), + (-0.00527482619509-0.00698099425063j), + (-0.0151527002454+0.036265052855j), + (0.0199296213686+0.0452499426901j), + (0.0122985243797+0.0143278446048j)) + src = gr.vector_source_s(self.src_data) + op = filter.freq_xlating_fir_filter_scc(1, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + + def test_fir_filter_scc_002(self): + self.generate_scc_source() + expected_data = ((-0.0080680437386-0.00158522999845j), + (-0.0037795654498+0.00733159901574j), + (0.00842926371843+0.00777021236718j), + (0.0112090632319-0.00249325321056j), + (-0.0027476802934-0.0115710813552j), + (-0.0158688724041-0.00715934624895j), + (-0.00802888441831+0.00620818417519j), + (0.0131985172629+0.0149175003171j), + (0.0190298333764+0.00956719089299j), + (-0.00112380902283-0.00936658866704j), + (-0.0204226914793-0.0333464704454j), + (-0.00695514678955-0.0437445007265j), + (0.0314490310848-0.0207983348519j), + (0.0529675260186+0.0302227605134j), + (0.0317338332534+0.0667510479689j), + (-0.00775565672666+0.0437112376094j), + (-0.024347923696-0.0303014591336j), + (-0.0108893103898-0.0875638127327j), + (0.00204296782613-0.0721434056759j), + (-0.00527479872108-0.00698097236454j)) + src = gr.vector_source_s(self.src_data) + op = filter.freq_xlating_fir_filter_scc(4, self.taps, self.fc, self.fs) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_data, result_data[-20:], 5) + +if __name__ == '__main__': + gr_unittest.run(test_freq_xlating_filter, "test_freq_xlating_filter.xml") + diff --git a/gr-filter/python/qa_hilbert.py b/gr-filter/python/qa_hilbert.py new file mode 100755 index 0000000000..b460b6438f --- /dev/null +++ b/gr-filter/python/qa_hilbert.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_hilbert(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_hilbert(self): + tb = self.tb + ntaps = 51 + sampling_freq = 100 + + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + src1 = gr.sig_source_f(sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + + head = gr.head(gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + hilb = filter.hilbert_fc(ntaps) + dst1 = gr.vector_sink_c() + tb.connect(src1, head) + tb.connect(head, hilb) + tb.connect(hilb, dst1) + tb.run() + dst_data = dst1.data() + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_hilbert, "test_hilbert.xml") diff --git a/gr-filter/python/qa_iir_filter.py b/gr-filter/python/qa_iir_filter.py new file mode 100755 index 0000000000..645c4b66e7 --- /dev/null +++ b/gr-filter/python/qa_iir_filter.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter + +class test_iir_filter(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_iir_direct_001(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = () + fbtaps = () + expected_result = (0, 0, 0, 0, 0, 0, 0, 0) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_002(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2,) + fbtaps = (0,) + expected_result = (2, 4, 6, 8, 10, 12, 14, 16) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_003(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, 0) + expected_result = (2, 15, 28, 41, 54, 67, 80, 93) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_004(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, -1) + expected_result = (2, 13, 15, 26, 28, 39, 41, 52) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_005(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_006(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + fftaps = (2, 1) + fbtaps = (0, -1) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + op.set_taps(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_007(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2,2,5,5,8,8,11,11) + fftaps = (2, 1) + fbtaps = (0, -1) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + fftaps = (2,0,1) + fbtaps = (0, -1) + op.set_taps(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_iir_direct_008(self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2,4,4,10,18,14,26,56) + fftaps = (2,) + fbtaps = (0, 1) + src = gr.vector_source_f(src_data) + op = filter.iir_filter_ffd(fftaps, fbtaps) + fftaps_data = (1) + fbtaps = (0,0, -1,3) + op.set_taps(fftaps, fbtaps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_iir_filter, "test_iir_filter.xml") + diff --git a/gr-filter/python/qa_interp_fir_filter.py b/gr-filter/python/qa_interp_fir_filter.py new file mode 100755 index 0000000000..839330539b --- /dev/null +++ b/gr-filter/python/qa_interp_fir_filter.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,2010,2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_interp_fir_filter(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_fff(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0, + 2,20,200,2003,20030, + 300,3005,30050, + 500,5007,50070, + 700,7011,70110, + 1100,11013,110130, + 1300,13017,130170) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = filter.interp_fir_filter_fff(interpolation, taps) + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data() + L = min(len(result_data), len(expected_result)) + self.assertEqual(expected_result[0:L], result_data[0:L]) + +if __name__ == '__main__': + gr_unittest.run(test_interp_fir_filter, "test_interp_fir_filter.xml") + diff --git a/gr-filter/python/qa_pfb_arb_resampler.py b/gr-filter/python/qa_pfb_arb_resampler.py new file mode 100755 index 0000000000..a4e22f4c02 --- /dev/null +++ b/gr-filter/python/qa_pfb_arb_resampler.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_pfb_arb_resampler(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_fff_000(self): + N = 1000 # number of samples to use + fs = 1000 # baseband sampling rate + rrate = 1.123 # resampling rate + + nfilts = 32 + taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + freq = 100 + signal = gr.sig_source_f(fs, gr.GR_SIN_WAVE, freq, 1) + head = gr.head(gr.sizeof_float, N) + pfb = filter.pfb_arb_resampler_fff(rrate, taps) + snk = gr.vector_sink_f() + + self.tb.connect(signal, head, pfb, snk) + self.tb.run() + + Ntest = 50 + L = len(snk.data()) + t = map(lambda x: float(x)/(fs*rrate), xrange(L)) + + phase = 0.53013 + expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t) + + dst_data = snk.data() + self.assertFloatTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3) + + def test_ccf_000(self): + N = 1000 # number of samples to use + fs = 1000 # baseband sampling rate + rrate = 1.123 # resampling rate + + nfilts = 32 + taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + freq = 100 + signal = gr.sig_source_c(fs, gr.GR_SIN_WAVE, freq, 1) + head = gr.head(gr.sizeof_gr_complex, N) + pfb = filter.pfb_arb_resampler_ccf(rrate, taps) + snk = gr.vector_sink_c() + + self.tb.connect(signal, head, pfb, snk) + self.tb.run() + + Ntest = 50 + L = len(snk.data()) + t = map(lambda x: float(x)/(fs*rrate), xrange(L)) + + phase = 0.53013 + expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase), t) + + dst_data = snk.data() + self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3) + +if __name__ == '__main__': + gr_unittest.run(test_pfb_arb_resampler, "test_pfb_arb_resampler.xml") diff --git a/gr-filter/python/qa_pfb_channelizer.py b/gr-filter/python/qa_pfb_channelizer.py new file mode 100755 index 0000000000..c0ed8327df --- /dev/null +++ b/gr-filter/python/qa_pfb_channelizer.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_pfb_channelizer(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + N = 1000 # number of samples to use + M = 5 # Number of channels to channelize + fs = 1000 # baseband sampling rate + ifs = M*fs # input samp rate to channelizer + + taps = filter.firdes.low_pass_2(1, ifs, 500, 50, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + signals = list() + add = gr.add_cc() + freqs = [-200, -100, 0, 100, 200] + for i in xrange(len(freqs)): + f = freqs[i] + (M/2-M+i+1)*fs + signals.append(gr.sig_source_c(ifs, gr.GR_SIN_WAVE, f, 1)) + self.tb.connect(signals[i], (add,i)) + + head = gr.head(gr.sizeof_gr_complex, N) + s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, M) + pfb = filter.pfb_channelizer_ccf(M, taps, 1) + + self.tb.connect(add, head, s2ss) + + snks = list() + for i in xrange(M): + snks.append(gr.vector_sink_c()) + self.tb.connect((s2ss,i), (pfb,i)) + self.tb.connect((pfb, i), snks[i]) + + self.tb.run() + + Ntest = 50 + L = len(snks[0].data()) + t = map(lambda x: float(x)/fs, xrange(L)) + + # Adjusted phase rotations for data + p0 = 0 + p1 = math.pi*0.51998885 + p2 = -math.pi*0.96002233 + p3 = math.pi*0.96002233 + p4 = -math.pi*0.51998885 + + # Create known data as complex sinusoids at the different baseband freqs + # the different channel numbering is due to channelizer output order. + expected0_data = map(lambda x: math.cos(2.*math.pi*freqs[2]*x+p0) + \ + 1j*math.sin(2.*math.pi*freqs[2]*x+p0), t) + expected1_data = map(lambda x: math.cos(2.*math.pi*freqs[3]*x+p1) + \ + 1j*math.sin(2.*math.pi*freqs[3]*x+p1), t) + expected2_data = map(lambda x: math.cos(2.*math.pi*freqs[4]*x+p2) + \ + 1j*math.sin(2.*math.pi*freqs[4]*x+p2), t) + expected3_data = map(lambda x: math.cos(2.*math.pi*freqs[0]*x+p3) + \ + 1j*math.sin(2.*math.pi*freqs[0]*x+p3), t) + expected4_data = map(lambda x: math.cos(2.*math.pi*freqs[1]*x+p4) + \ + 1j*math.sin(2.*math.pi*freqs[1]*x+p4), t) + + dst0_data = snks[0].data() + dst1_data = snks[1].data() + dst2_data = snks[2].data() + dst3_data = snks[3].data() + dst4_data = snks[4].data() + + self.assertComplexTuplesAlmostEqual(expected0_data[-Ntest:], dst0_data[-Ntest:], 3) + self.assertComplexTuplesAlmostEqual(expected1_data[-Ntest:], dst1_data[-Ntest:], 3) + self.assertComplexTuplesAlmostEqual(expected2_data[-Ntest:], dst2_data[-Ntest:], 3) + self.assertComplexTuplesAlmostEqual(expected3_data[-Ntest:], dst3_data[-Ntest:], 3) + self.assertComplexTuplesAlmostEqual(expected4_data[-Ntest:], dst4_data[-Ntest:], 3) + +if __name__ == '__main__': + gr_unittest.run(test_pfb_channelizer, "test_pfb_channelizer.xml") diff --git a/gr-filter/python/qa_pfb_decimator.py b/gr-filter/python/qa_pfb_decimator.py new file mode 100755 index 0000000000..063845f638 --- /dev/null +++ b/gr-filter/python/qa_pfb_decimator.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_pfb_decimator(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + N = 1000 # number of samples to use + M = 5 # Number of channels + fs = 1000 # baseband sampling rate + ifs = M*fs # input samp rate to decimator + channel = 0 # Extract channel 0 + + taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + signals = list() + add = gr.add_cc() + freqs = [-200, -100, 0, 100, 200] + for i in xrange(len(freqs)): + f = freqs[i] + (M/2-M+i+1)*fs + signals.append(gr.sig_source_c(ifs, gr.GR_SIN_WAVE, f, 1)) + self.tb.connect(signals[i], (add,i)) + + head = gr.head(gr.sizeof_gr_complex, N) + s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, M) + pfb = filter.pfb_decimator_ccf(M, taps, channel) + snk = gr.vector_sink_c() + + self.tb.connect(add, head, s2ss) + for i in xrange(M): + self.tb.connect((s2ss,i), (pfb,i)) + self.tb.connect(pfb, snk) + + self.tb.run() + + Ntest = 50 + L = len(snk.data()) + t = map(lambda x: float(x)/fs, xrange(L)) + + # Create known data as complex sinusoids for the baseband freq + # of the extracted channel is due to decimator output order. + phase = 0 + expected_data = map(lambda x: math.cos(2.*math.pi*freqs[2]*x+phase) + \ + 1j*math.sin(2.*math.pi*freqs[2]*x+phase), t) + + dst_data = snk.data() + + self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4) + + def test_001(self): + N = 1000 # number of samples to use + M = 5 # Number of channels + fs = 1000 # baseband sampling rate + ifs = M*fs # input samp rate to decimator + channel = 1 # Extract channel 0 + + taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + signals = list() + add = gr.add_cc() + freqs = [-200, -100, 0, 100, 200] + for i in xrange(len(freqs)): + f = freqs[i] + (M/2-M+i+1)*fs + signals.append(gr.sig_source_c(ifs, gr.GR_SIN_WAVE, f, 1)) + self.tb.connect(signals[i], (add,i)) + + head = gr.head(gr.sizeof_gr_complex, N) + s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, M) + pfb = filter.pfb_decimator_ccf(M, taps, channel) + snk = gr.vector_sink_c() + + self.tb.connect(add, head, s2ss) + for i in xrange(M): + self.tb.connect((s2ss,i), (pfb,i)) + self.tb.connect(pfb, snk) + + self.tb.run() + + Ntest = 50 + L = len(snk.data()) + t = map(lambda x: float(x)/fs, xrange(L)) + + # Create known data as complex sinusoids for the baseband freq + # of the extracted channel is due to decimator output order. + phase = 6.15746 + expected_data = map(lambda x: math.cos(2.*math.pi*freqs[3]*x+phase) + \ + 1j*math.sin(2.*math.pi*freqs[3]*x+phase), t) + dst_data = snk.data() + + self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4) + +if __name__ == '__main__': + gr_unittest.run(test_pfb_decimator, "test_pfb_decimator.xml") diff --git a/gr-filter/python/qa_pfb_interpolator.py b/gr-filter/python/qa_pfb_interpolator.py new file mode 100755 index 0000000000..5b84b7c642 --- /dev/null +++ b/gr-filter/python/qa_pfb_interpolator.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_pfb_interpolator(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + N = 1000 # number of samples to use + M = 5 # Number of channels + fs = 1000 # baseband sampling rate + ifs = M*fs # input samp rate to decimator + + taps = filter.firdes.low_pass_2(M, ifs, fs/2, fs/10, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + freq = 100 + signal = gr.sig_source_c(fs, gr.GR_COS_WAVE, freq, 1) + head = gr.head(gr.sizeof_gr_complex, N) + pfb = filter.pfb_interpolator_ccf(M, taps) + snk = gr.vector_sink_c() + + self.tb.connect(signal, head, pfb) + self.tb.connect(pfb, snk) + + self.tb.run() + + Ntest = 50 + L = len(snk.data()) + t = map(lambda x: float(x)/ifs, xrange(L)) + + # Create known data as complex sinusoids at freq + # of the channel at the interpolated rate. + phase = 0.62833 + expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase), t) + + dst_data = snk.data() + + self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4) + +if __name__ == '__main__': + gr_unittest.run(test_pfb_interpolator, "test_pfb_interpolator.xml") diff --git a/gr-filter/python/qa_pfb_synthesizer.py b/gr-filter/python/qa_pfb_synthesizer.py new file mode 100755 index 0000000000..e8164d2683 --- /dev/null +++ b/gr-filter/python/qa_pfb_synthesizer.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math + +class test_pfb_synthesizer(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + N = 10000 # number of samples to use + M = 5 # Number of channels + fs = 1000 # baseband sampling rate + ofs = M*fs # input samp rate to decimator + + taps = filter.firdes.low_pass_2(M, ofs, fs/2, fs/10, + attenuation_dB=80, + window=filter.firdes.WIN_BLACKMAN_hARRIS) + + signals = list() + freqs = [0, 100, 200, -200, -100] + for i in xrange(len(freqs)): + signals.append(gr.sig_source_c(fs, gr.GR_SIN_WAVE, freqs[i], 1)) + + head = gr.head(gr.sizeof_gr_complex, N) + pfb = filter.pfb_synthesizer_ccf(M, taps) + snk = gr.vector_sink_c() + + for i in xrange(M): + self.tb.connect(signals[i], (pfb,i)) + + self.tb.connect(pfb, head, snk) + + self.tb.run() + + Ntest = 1000 + L = len(snk.data()) + t = map(lambda x: float(x)/ofs, xrange(L)) + + # Create known data as sum of complex sinusoids at freqs + # of the output channels. + freqs = [-2200, -1100, 0, 1100, 2200] + expected_data = len(t)*[0,] + for i in xrange(len(t)): + expected_data[i] = math.cos(2.*math.pi*freqs[0]*t[i]) + \ + 1j*math.sin(2.*math.pi*freqs[0]*t[i]) + \ + math.cos(2.*math.pi*freqs[1]*t[i]) + \ + 1j*math.sin(2.*math.pi*freqs[1]*t[i]) + \ + math.cos(2.*math.pi*freqs[2]*t[i]) + \ + 1j*math.sin(2.*math.pi*freqs[2]*t[i]) + \ + math.cos(2.*math.pi*freqs[3]*t[i]) + \ + 1j*math.sin(2.*math.pi*freqs[3]*t[i]) + \ + math.cos(2.*math.pi*freqs[4]*t[i]) + \ + 1j*math.sin(2.*math.pi*freqs[4]*t[i]) + dst_data = snk.data() + + offset = 25 + self.assertComplexTuplesAlmostEqual(expected_data[2000-offset:2000-offset+Ntest], + dst_data[2000:2000+Ntest], 4) + +if __name__ == '__main__': + gr_unittest.run(test_pfb_synthesizer, "test_pfb_synthesizer.xml") diff --git a/gr-filter/python/qa_pm_remez.py b/gr-filter/python/qa_pm_remez.py new file mode 100755 index 0000000000..a76e14c938 --- /dev/null +++ b/gr-filter/python/qa_pm_remez.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python +# +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import sys, math + +# ---------------------------------------------------------------- +# See optfir for an explanation of these. + +def stopband_atten_to_dev (atten_db): + """Convert a stopband attenuation in dB to an absolute value""" + return 10**(-atten_db/20) + +def passband_ripple_to_dev (ripple_db): + """Convert passband ripple spec expressed in dB to an absolute value""" + return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + +# ---------------------------------------------------------------- + +def remezord (fcuts, mags, devs, fsamp = 2): + ''' + FIR order estimator (lowpass, highpass, bandpass, mulitiband). + ''' + + # get local copies + fcuts = fcuts[:] + mags = mags[:] + devs = devs[:] + + for i in range (len (fcuts)): + fcuts[i] = float (fcuts[i]) / fsamp + + nf = len (fcuts) + nm = len (mags) + nd = len (devs) + nbands = nm + + if nm != nd: + raise ValueError, "Length of mags and devs must be equal" + + if nf != 2 * (nbands - 1): + raise ValueError, "Length of f must be 2 * len (mags) - 2" + + for i in range (len (mags)): + if mags[i] != 0: # if not stopband, get relative deviation + devs[i] = devs[i] / mags[i] + + # separate the passband and stopband edges + f1 = fcuts[0::2] + f2 = fcuts[1::2] + + n = 0 + min_delta = 2 + for i in range (len (f1)): + if f2[i] - f1[i] < min_delta: + n = i + min_delta = f2[i] - f1[i] + + if nbands == 2: + # lowpass or highpass case (use formula) + l = lporder (f1[n], f2[n], devs[0], devs[1]) + else: + # bandpass or multipass case + # try different lowpasses and take the worst one that + # goes through the BP specs + l = 0 + for i in range (1, nbands-1): + l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1]) + l2 = lporder (f1[i], f2[i], devs[i], devs[i+1]) + l = max (l, l1, l2) + + n = int (math.ceil (l)) - 1 # need order, not length for remez + + # cook up remez compatible result + ff = [0] + fcuts + [1] + for i in range (1, len (ff) - 1): + ff[i] *= 2 + + aa = [] + for a in mags: + aa = aa + [a, a] + + max_dev = max (devs) + wts = [1] * len(devs) + for i in range (len (wts)): + wts[i] = max_dev / devs[i] + + return (n, ff, aa, wts) + + +def lporder (freq1, freq2, delta_p, delta_s): + ''' + FIR lowpass filter length estimator. + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 5.309e-3 + a2 = 7.114e-2 + a3 = -4.761e-1 + a4 = -2.66e-3 + a5 = -5.941e-1 + a6 = -4.278e-1 + + b1 = 11.01217 + b2 = 0.5124401 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6) + ff = b1 + b2 * (ddp - dds) + n = dinf / df - ff * df + 1 + return n + +# ---------------------------------------------------------------- + +class test_pm_remez(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_low_pass(self): + gain = 1 + Fs = 1 + freq1 = 0.1 + freq2 = 0.2 + passband_ripple_db = 0.01 + stopband_atten_db = 60 + + passband_dev = passband_ripple_to_dev(passband_ripple_db) + stopband_dev = stopband_atten_to_dev(stopband_atten_db) + desired_ampls = (gain, 0) + (n, fo, ao, w) = remezord([freq1, freq2], desired_ampls, + [passband_dev, stopband_dev], Fs) + new_taps = filter.pm_remez(n + 2, fo, ao, w, "bandpass") + + known_taps = (-0.0008370135734511828, -0.0006622211673134374, + 0.0008501079576365787, 0.003059609130249229, + 0.003202235537205373, -0.001000899296974219, + -0.007589728680590891, -0.009790921118281865, + -0.001524210202628562, 0.014373535837200111, + 0.02392881326993834, 0.011798133085019008, + -0.021954446348997188, -0.05293436740264934, + -0.04375787096766848, 0.028038890498420392, + 0.14612655590172896, 0.25738578419108626, + 0.302967004188747, 0.25738578419108626, + 0.14612655590172896, 0.028038890498420392, + -0.04375787096766848, -0.05293436740264934, + -0.021954446348997188, 0.011798133085019008, + 0.02392881326993834, 0.014373535837200111, + -0.001524210202628562, -0.009790921118281865, + -0.007589728680590891, -0.001000899296974219, + 0.003202235537205373, 0.003059609130249229, + 0.0008501079576365787, -0.0006622211673134374, + -0.0008370135734511828) + + self.assertFloatTuplesAlmostEqual(known_taps, new_taps, 5) + +if __name__ == '__main__': + gr_unittest.run(test_pm_remez, "test_pm_remez.xml") + diff --git a/gr-filter/python/qa_rational_resampler.py b/gr-filter/python/qa_rational_resampler.py new file mode 100755 index 0000000000..eb86ef5425 --- /dev/null +++ b/gr-filter/python/qa_rational_resampler.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006,2007,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter +import math +import random +import sys + + +def random_floats(n): + r = [] + for x in xrange(n): + # r.append(float(random.randint(-32768, 32768))) + r.append(float(random.random())) + return tuple(r) + + +def reference_dec_filter(src_data, decim, taps): + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + tb = None + return result_data + +def reference_interp_filter(src_data, interp, taps): + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.interp_fir_filter_fff(interp, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + tb = None + return result_data + +def reference_interp_dec_filter(src_data, interp, decim, taps): + tb = gr.top_block() + src = gr.vector_source_f(src_data) + up = filter.interp_fir_filter_fff(interp, (1,)) + dn = filter.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + tb.connect(src, up, dn, dst) + tb.run() + result_data = dst.data() + tb = None + return result_data + + +class test_rational_resampler (gr_unittest.TestCase): + + def setUp(self): + random.seed(0) + + def tearDown(self): + pass + + + def test_000_1_to_1(self): + taps = (-4, 5) + src_data = (234, -4, 23, -56, 45, 98, -23, -7) + xr = (1186, -112, 339, -460, -167, 582) + expected_result = tuple([float(x) for x in xr]) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(1, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_001_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,2,20,200,2003,20030, + 300,3005,30050, + 500,5007,50070, + 700,7011,70110, + 1100,11013,110130, + 1300,13017,130170, + 1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002_interp(self): + taps = random_floats(31) + src_data = random_floats(10000) + interpolation = 3 + + expected_result = reference_interp_filter(src_data, interpolation, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + + N = 1000 + offset = len(taps)-1 + self.assertEqual(expected_result[offset:offset+N], result_data[0:N]) + + def xtest_003_interp(self): + taps = random_floats(9) + src_data = random_floats(10000) + decimation = 3 + + expected_result = reference_dec_filter(src_data, decimation, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(1, decimation, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + + N = 10 + offset = 10#len(taps)-1 + print expected_result[100+offset:100+offset+N] + print result_data[100:100+N] + #self.assertEqual(expected_result[offset:offset+N], result_data[0:N]) + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_004_decim_random_vals(self): + MAX_TAPS = 9 + MAX_DECIM = 7 + OUTPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for decim in xrange(1, MAX_DECIM+1): + for ilen in xrange(ntaps + decim, ntaps + OUTPUT_LEN*decim): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_dec_filter(src_data, decim, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(1, decim, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + tb = None + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % (L2 - L1, ntaps, decim, ilen)) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_005_interp_random_vals(self): + MAX_TAPS = 9 + MAX_INTERP = 7 + INPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for interp in xrange(1, MAX_INTERP+1): + for ilen in xrange(ntaps, ntaps + INPUT_LEN): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_interp_filter(src_data, interp, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(interp, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + tb = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + #if True or abs(L1-L2) > 1: + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % (L2 - L1, ntaps, interp, ilen)) + #sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + # (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first ntaps+1 answers + self.assertEqual(expected_result[ntaps+1:L], result_data[ntaps+1:L]) + + def test_006_interp_decim(self): + taps = random_floats(31) + src_data = random_floats(10000) + interp = 3 + decimation = 2 + + expected_result = reference_interp_dec_filter(src_data, interp, decimation, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = filter.rational_resampler_base_fff(interp, decimation, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + + N = 1000 + offset = len(taps)/2 + self.assertFloatTuplesAlmostEqual(expected_result[offset:offset+N], result_data[0:N], 5) + + +if __name__ == '__main__': + # FIXME: Disabled, see ticket:210 + gr_unittest.run(test_rational_resampler, "test_rational_resampler.xml") + diff --git a/gr-filter/python/qa_single_pole_iir.py b/gr-filter/python/qa_single_pole_iir.py new file mode 100755 index 0000000000..3608c77f95 --- /dev/null +++ b/gr-filter/python/qa_single_pole_iir.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# +# Copyright 2005,2007,2010 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import filter_swig as filter + +class test_single_pole_iir_filter(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_ff_001(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = src_data + src = gr.vector_source_f(src_data) + op = filter.single_pole_iir_filter_ff(1.0) + dst = gr.vector_sink_f() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_ff_002(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 359.375, 689.453125, 1103.271484, 1590.36255) + src = gr.vector_source_f(src_data) + op = filter.single_pole_iir_filter_ff(0.125) + dst = gr.vector_sink_f() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data, 3) + + def test_ff_003(self): + block_size = 2 + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 250, 484.375, 718.75, 1048.828125) + src = gr.vector_source_f(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_float, block_size) + op = filter.single_pole_iir_filter_ff (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_float, block_size) + dst = gr.vector_sink_f() + self.tb.connect(src, s2p, op, p2s, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual(expected_result, result_data, 3) + + def test_cc_001(self): + src_data = (0+0j, 1000+1000j, 2000+2000j, 3000+3000j, 4000+4000j, 5000+5000j) + expected_result = src_data + src = gr.vector_source_c(src_data) + op = filter.single_pole_iir_filter_cc(1.0) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data) + + def test_cc_002(self): + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), + complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(359.375,-359.375), + complex(689.453125,-689.453125), complex(1103.271484,-1103.271484), + complex(1590.36255,-1590.36255)) + src = gr.vector_source_c(src_data) + op = filter.single_pole_iir_filter_cc(0.125) + dst = gr.vector_sink_c() + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 3) + + def test_cc_003(self): + block_size = 2 + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), + complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(250,-250), + complex(484.375,-484.375), complex(718.75,-718.75), + complex(1048.828125,-1048.828125)) + src = gr.vector_source_c(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, block_size) + op = filter.single_pole_iir_filter_cc(0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_gr_complex, block_size) + dst = gr.vector_sink_c() + self.tb.connect(src, s2p, op, p2s, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual(expected_result, result_data, 3) + +if __name__ == '__main__': + gr_unittest.run(test_single_pole_iir_filter, "test_single_pole_iir_filter.xml") + diff --git a/gr-filter/python/rational_resampler.py b/gr-filter/python/rational_resampler.py new file mode 100644 index 0000000000..312b011d32 --- /dev/null +++ b/gr-filter/python/rational_resampler.py @@ -0,0 +1,129 @@ +# +# Copyright 2005,2007 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gru + +_plot = None + +def design_filter(interpolation, decimation, fractional_bw): + """ + Given the interpolation rate, decimation rate and a fractional bandwidth, + design a set of taps. + + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well. + @type fractional_bw: float + @returns: sequence of numbers + """ + + if fractional_bw >= 0.5 or fractional_bw <= 0: + raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)" + + beta = 5.0 + trans_width = 0.5 - fractional_bw + mid_transition_band = 0.5 - trans_width/2 + + taps = filter.firdes.low_pass(interpolation, # gain + 1, # Fs + mid_transition_band/interpolation, # trans mid point + trans_width/interpolation, # transition width + filter.firdes.WIN_KAISER, + beta) # beta + return taps + + + +class _rational_resampler_base(gr.hier_block2): + """ + base class for all rational resampler variants. + """ + def __init__(self, resampler_base, + interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter. + + Either taps or fractional_bw may be specified, but not both. + If neither is specified, a reasonable default, 0.4, is used as + the fractional_bw. + + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param taps: optional filter coefficients + @type taps: sequence + @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4) + @type fractional_bw: float + """ + + if not isinstance(interpolation, int) or interpolation < 1: + raise ValueError, "interpolation must be an integer >= 1" + + if not isinstance(decimation, int) or decimation < 1: + raise ValueError, "decimation must be an integer >= 1" + + if taps is None and fractional_bw is None: + fractional_bw = 0.4 + + d = gru.gcd(interpolation, decimation) + interpolation = interpolation // d + decimation = decimation // d + + if taps is None: + taps = design_filter(interpolation, decimation, fractional_bw) + + resampler = resampler_base(interpolation, decimation, taps) + gr.hier_block2.__init__(self, "rational_resampler", + gr.io_signature(1, 1, resampler.input_signature().sizeof_stream_item(0)), + gr.io_signature(1, 1, resampler.output_signature().sizeof_stream_item(0))) + + self.connect(self, resampler, self) + + +class rational_resampler_fff(_rational_resampler_base): + def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + float input, float output and float taps. + """ + _rational_resampler_base.__init__(self, filter.rational_resampler_base_fff, + interpolation, decimation, taps, fractional_bw) + +class rational_resampler_ccf(_rational_resampler_base): + def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and float taps. + """ + _rational_resampler_base.__init__(self, filter.rational_resampler_base_ccf, + interpolation, decimation, taps, fractional_bw) + +class rational_resampler_ccc(_rational_resampler_base): + def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and complex taps. + """ + _rational_resampler_base.__init__(self, filter.rational_resampler_base_ccc, + interpolation, decimation, taps, fractional_bw) diff --git a/gr-filter/swig/CMakeLists.txt b/gr-filter/swig/CMakeLists.txt new file mode 100644 index 0000000000..3eee3a1ee4 --- /dev/null +++ b/gr-filter/swig/CMakeLists.txt @@ -0,0 +1,53 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup swig generation +######################################################################## +include(GrPython) +include(GrSwig) + +set(GR_SWIG_INCLUDE_DIRS + ${GR_FILTER_INCLUDE_DIRS} + ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} + ${FFT_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} +) + +# FIXME: rename to filter_swig_doc.i when gnuradio-core is updated +set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i) +set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) + +set(GR_SWIG_LIBRARIES gnuradio-filter gnuradio-fft) + +GR_SWIG_MAKE(filter_swig filter_swig.i) + +GR_SWIG_INSTALL( + TARGETS filter_swig + DESTINATION ${GR_PYTHON_DIR}/gnuradio/filter + COMPONENT "filter_python" +) + +install( + FILES + filter_swig.i + ${CMAKE_CURRENT_BINARY_DIR}/gr_filter_swig_doc.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "filter_swig" +) diff --git a/gr-filter/swig/filter_swig.i b/gr-filter/swig/filter_swig.i new file mode 100644 index 0000000000..05b84d4d69 --- /dev/null +++ b/gr-filter/swig/filter_swig.i @@ -0,0 +1,169 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#define FILTER_API + +%include "gnuradio.i" + +//load generated python docstrings +%include "gr_filter_swig_doc.i" + +%{ +#include "filter/firdes.h" +#include "filter/pm_remez.h" +#include "filter/adaptive_fir_ccc.h" +#include "filter/adaptive_fir_ccf.h" +#include "filter/dc_blocker_cc.h" +#include "filter/dc_blocker_ff.h" +#include "filter/filter_delay_fc.h" +#include "filter/fir_filter_ccc.h" +#include "filter/fir_filter_ccf.h" +#include "filter/fir_filter_fcc.h" +#include "filter/fir_filter_fff.h" +#include "filter/fir_filter_fsf.h" +#include "filter/fir_filter_scc.h" +#include "filter/fft_filter_ccc.h" +#include "filter/fft_filter_fff.h" +#include "filter/fractional_interpolator_cc.h" +#include "filter/fractional_interpolator_ff.h" +#include "filter/freq_xlating_fir_filter_ccc.h" +#include "filter/freq_xlating_fir_filter_ccf.h" +#include "filter/freq_xlating_fir_filter_fcc.h" +#include "filter/freq_xlating_fir_filter_fcf.h" +#include "filter/freq_xlating_fir_filter_scf.h" +#include "filter/freq_xlating_fir_filter_scc.h" +#include "filter/hilbert_fc.h" +#include "filter/iir_filter_ffd.h" +#include "filter/interp_fir_filter_ccc.h" +#include "filter/interp_fir_filter_ccf.h" +#include "filter/interp_fir_filter_fcc.h" +#include "filter/interp_fir_filter_fff.h" +#include "filter/interp_fir_filter_fsf.h" +#include "filter/interp_fir_filter_scc.h" +#include "filter/pfb_arb_resampler_ccf.h" +#include "filter/pfb_arb_resampler_fff.h" +#include "filter/pfb_channelizer_ccf.h" +#include "filter/pfb_decimator_ccf.h" +#include "filter/pfb_interpolator_ccf.h" +#include "filter/pfb_synthesizer_ccf.h" +#include "filter/rational_resampler_base_ccc.h" +#include "filter/rational_resampler_base_ccf.h" +#include "filter/rational_resampler_base_fcc.h" +#include "filter/rational_resampler_base_fff.h" +#include "filter/rational_resampler_base_fsf.h" +#include "filter/rational_resampler_base_scc.h" +#include "filter/single_pole_iir_filter_cc.h" +#include "filter/single_pole_iir_filter_ff.h" +#include "filter/channel_model.h" +%} + +%include "filter/firdes.h" +%include "filter/pm_remez.h" +%include "filter/adaptive_fir_ccc.h" +%include "filter/adaptive_fir_ccf.h" +%include "filter/dc_blocker_cc.h" +%include "filter/dc_blocker_ff.h" +%include "filter/filter_delay_fc.h" +%include "filter/fir_filter_ccc.h" +%include "filter/fir_filter_ccf.h" +%include "filter/fir_filter_fcc.h" +%include "filter/fir_filter_fff.h" +%include "filter/fir_filter_fsf.h" +%include "filter/fir_filter_scc.h" +%include "filter/fft_filter_ccc.h" +%include "filter/fft_filter_fff.h" +%include "filter/fractional_interpolator_cc.h" +%include "filter/fractional_interpolator_ff.h" +%include "filter/freq_xlating_fir_filter_ccc.h" +%include "filter/freq_xlating_fir_filter_ccf.h" +%include "filter/freq_xlating_fir_filter_fcc.h" +%include "filter/freq_xlating_fir_filter_fcf.h" +%include "filter/freq_xlating_fir_filter_scf.h" +%include "filter/freq_xlating_fir_filter_scc.h" +%include "filter/hilbert_fc.h" +%include "filter/iir_filter_ffd.h" +%include "filter/interp_fir_filter_ccc.h" +%include "filter/interp_fir_filter_ccf.h" +%include "filter/interp_fir_filter_fcc.h" +%include "filter/interp_fir_filter_fff.h" +%include "filter/interp_fir_filter_fsf.h" +%include "filter/interp_fir_filter_scc.h" +%include "filter/pfb_arb_resampler_ccf.h" +%include "filter/pfb_arb_resampler_fff.h" +%include "filter/pfb_channelizer_ccf.h" +%include "filter/pfb_decimator_ccf.h" +%include "filter/pfb_interpolator_ccf.h" +%include "filter/pfb_synthesizer_ccf.h" +%include "filter/rational_resampler_base_ccc.h" +%include "filter/rational_resampler_base_ccf.h" +%include "filter/rational_resampler_base_fcc.h" +%include "filter/rational_resampler_base_fff.h" +%include "filter/rational_resampler_base_fsf.h" +%include "filter/rational_resampler_base_scc.h" +%include "filter/single_pole_iir_filter_cc.h" +%include "filter/single_pole_iir_filter_ff.h" +%include "filter/channel_model.h" + +GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccc); +GR_SWIG_BLOCK_MAGIC2(filter, adaptive_fir_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_cc); +GR_SWIG_BLOCK_MAGIC2(filter, dc_blocker_ff); +GR_SWIG_BLOCK_MAGIC2(filter, filter_delay_fc); +GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccc); +GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fcc); +GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fff); +GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_fsf); +GR_SWIG_BLOCK_MAGIC2(filter, fir_filter_scc); +GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_ccc); +GR_SWIG_BLOCK_MAGIC2(filter, fft_filter_fff); +GR_SWIG_BLOCK_MAGIC2(filter, fractional_interpolator_cc); +GR_SWIG_BLOCK_MAGIC2(filter, fractional_interpolator_ff); +GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_ccc); +GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_fcc); +GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_fcf); +GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_scf); +GR_SWIG_BLOCK_MAGIC2(filter, freq_xlating_fir_filter_scc); +GR_SWIG_BLOCK_MAGIC2(filter, hilbert_fc); +GR_SWIG_BLOCK_MAGIC2(filter, iir_filter_ffd); +GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_ccc); +GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fcc); +GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fff); +GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_fsf); +GR_SWIG_BLOCK_MAGIC2(filter, interp_fir_filter_scc); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_arb_resampler_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_arb_resampler_fff); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_channelizer_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_decimator_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_interpolator_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, pfb_synthesizer_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_ccc); +GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_ccf); +GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_fcc); +GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_fff); +GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_fsf); +GR_SWIG_BLOCK_MAGIC2(filter, rational_resampler_base_scc); +GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_cc); +GR_SWIG_BLOCK_MAGIC2(filter, single_pole_iir_filter_ff); +GR_SWIG_BLOCK_MAGIC2(filter, channel_model); diff --git a/gr-pager/apps/usrp_flex_all b/gr-pager/apps/usrp_flex_all index 75c4c1e737..8ecf5a41ff 100755 --- a/gr-pager/apps/usrp_flex_all +++ b/gr-pager/apps/usrp_flex_all @@ -98,9 +98,9 @@ class app_top_block(gr.top_block): mid_chan = int(self.nchan/2) for i in range(self.nchan): if i < mid_chan: - freq = 930.5e6+i*25e3 + freq = options.freq+i*25e3 else: - freq = 930.5e6-(self.nchan-i)*25e3 + freq = options.freq-(self.nchan-i)*25e3 if (freq < 929.0e6 or freq > 932.0e6): self.connect((self.bank, i), gr.null_sink(gr.sizeof_gr_complex)) diff --git a/gr-trellis/doc/gr-trellis.xml b/gr-trellis/doc/gr-trellis.xml index 4657dab384..58aa74d409 100644 --- a/gr-trellis/doc/gr-trellis.xml +++ b/gr-trellis/doc/gr-trellis.xml @@ -587,7 +587,7 @@ outputs a sequence of D numbers ci1,ci2,...,ciD representing the coordianates of the constellation symbol c_i with i=y_k. </para> <programlisting> - 20 mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + 20 mod = digital.chunks_to_symbols_sf(constellation,dimensionality) </programlisting> <para> @@ -804,7 +804,7 @@ L being the channel length. This is sufficient to drive the initial and final st 23 packet[i] = 0 24 packet[len(packet)-i-1] = 0 25 src = gr.vector_source_s(packet,False) - 26 mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + 26 mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) </programlisting> diff --git a/gr-trellis/doc/test_tcm.py b/gr-trellis/doc/test_tcm.py index 8c046d697b..3a285e27a2 100644 --- a/gr-trellis/doc/test_tcm.py +++ b/gr-trellis/doc/test_tcm.py @@ -17,7 +17,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/doc/test_tcm.py.xml b/gr-trellis/doc/test_tcm.py.xml index b5074cb2f4..a4c541e38a 100644 --- a/gr-trellis/doc/test_tcm.py.xml +++ b/gr-trellis/doc/test_tcm.py.xml @@ -19,7 +19,7 @@ 17 src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts 18 s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality 19 enc = trellis.encoder_ss(f,0) # initial state = 0 - 20 mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + 20 mod = digital.chunks_to_symbols_sf(constellation,dimensionality) 21 22 # CHANNEL 23 add = gr.add_ff() diff --git a/gr-trellis/doc/test_viterbi_equalization1.py b/gr-trellis/doc/test_viterbi_equalization1.py index 5967384cf9..c9c897fe2e 100755 --- a/gr-trellis/doc/test_viterbi_equalization1.py +++ b/gr-trellis/doc/test_viterbi_equalization1.py @@ -23,7 +23,7 @@ def run_test (f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constel packet[i] = 0 packet[len(packet)-i-1] = 0 src = gr.vector_source_s(packet,False) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/doc/test_viterbi_equalization1.py.xml b/gr-trellis/doc/test_viterbi_equalization1.py.xml index 27605870e8..751633a618 100644 --- a/gr-trellis/doc/test_viterbi_equalization1.py.xml +++ b/gr-trellis/doc/test_viterbi_equalization1.py.xml @@ -25,7 +25,7 @@ 23 packet[i] = 0 24 packet[len(packet)-i-1] = 0 25 src = gr.vector_source_s(packet,False) - 26 mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + 26 mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) 27 28 # CHANNEL 29 isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/examples/python/test_cpm.py b/gr-trellis/src/examples/python/test_cpm.py index 5342e57e82..7503a458b1 100755 --- a/gr-trellis/src/examples/python/test_cpm.py +++ b/gr-trellis/src/examples/python/test_cpm.py @@ -89,7 +89,7 @@ def run_test(seed,blocksize): # Blocks ################################################## random_source_x_0 = gr.vector_source_b(data.tolist(), False) - gr_chunks_to_symbols_xx_0 = gr.chunks_to_symbols_bf((-1, 1), 1) + digital_chunks_to_symbols_xx_0 = digital.chunks_to_symbols_bf((-1, 1), 1) gr_interp_fir_filter_xxx_0 = gr.interp_fir_filter_fff(Q, p) gr_frequency_modulator_fc_0 = gr.frequency_modulator_fc(2*math.pi*h*(1.0/Q)) @@ -111,8 +111,8 @@ def run_test(seed,blocksize): ################################################## # Connections ################################################## - tb.connect((random_source_x_0, 0), (gr_chunks_to_symbols_xx_0, 0)) - tb.connect((gr_chunks_to_symbols_xx_0, 0), (gr_interp_fir_filter_xxx_0, 0)) + tb.connect((random_source_x_0, 0), (digital_chunks_to_symbols_xx_0, 0)) + tb.connect((digital_chunks_to_symbols_xx_0, 0), (gr_interp_fir_filter_xxx_0, 0)) tb.connect((gr_interp_fir_filter_xxx_0, 0), (gr_frequency_modulator_fc_0, 0)) tb.connect((gr_frequency_modulator_fc_0, 0), (gr_add_vxx_0, 0)) tb.connect((gr_noise_source_x_0, 0), (gr_add_vxx_0, 1)) diff --git a/gr-trellis/src/examples/python/test_pccc_turbo1.py b/gr-trellis/src/examples/python/test_pccc_turbo1.py index 0655b972de..abc0e1d01f 100755 --- a/gr-trellis/src/examples/python/test_pccc_turbo1.py +++ b/gr-trellis/src/examples/python/test_pccc_turbo1.py @@ -20,7 +20,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, #src = gr.vector_source_s([0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1],False) enc = trellis.pccc_encoder_ss(fo,0,fi,0,interleaver,K) code = gr.vector_sink_s() - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_hard.py b/gr-trellis/src/examples/python/test_sccc_hard.py index 4eeb94a12d..397ebf0871 100755 --- a/gr-trellis/src/examples/python/test_sccc_hard.py +++ b/gr-trellis/src/examples/python/test_sccc_hard.py @@ -19,7 +19,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_soft.py b/gr-trellis/src/examples/python/test_sccc_soft.py index 10c28419a8..b1ffaae748 100755 --- a/gr-trellis/src/examples/python/test_sccc_soft.py +++ b/gr-trellis/src/examples/python/test_sccc_soft.py @@ -22,7 +22,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_turbo.py b/gr-trellis/src/examples/python/test_sccc_turbo.py index 762a93ba51..e8054a08b2 100755 --- a/gr-trellis/src/examples/python/test_sccc_turbo.py +++ b/gr-trellis/src/examples/python/test_sccc_turbo.py @@ -61,7 +61,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_turbo1.py b/gr-trellis/src/examples/python/test_sccc_turbo1.py index 187a75185f..ef5d32f588 100755 --- a/gr-trellis/src/examples/python/test_sccc_turbo1.py +++ b/gr-trellis/src/examples/python/test_sccc_turbo1.py @@ -17,7 +17,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_sccc_turbo2.py b/gr-trellis/src/examples/python/test_sccc_turbo2.py index dff1ba93c3..942572676d 100755 --- a/gr-trellis/src/examples/python/test_sccc_turbo2.py +++ b/gr-trellis/src/examples/python/test_sccc_turbo2.py @@ -17,7 +17,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,constellation, src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the outer FSM input cardinality enc = trellis.sccc_encoder_ss(fo,0,fi,0,interleaver,K) - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_tcm.py b/gr-trellis/src/examples/python/test_tcm.py index a7d6a02d04..eff93f5b4e 100755 --- a/gr-trellis/src/examples/python/test_tcm.py +++ b/gr-trellis/src/examples/python/test_tcm.py @@ -24,7 +24,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): #b2s = gr.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_tcm_bit.py b/gr-trellis/src/examples/python/test_tcm_bit.py index 7f69c0e294..1a89d06a89 100755 --- a/gr-trellis/src/examples/python/test_tcm_bit.py +++ b/gr-trellis/src/examples/python/test_tcm_bit.py @@ -25,7 +25,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): b2s = gr.unpacked_to_packed_ss(1,gr.GR_MSB_FIRST) # pack bits in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL diff --git a/gr-trellis/src/examples/python/test_tcm_combined.py b/gr-trellis/src/examples/python/test_tcm_combined.py index d98e36e27d..a46444e32b 100755 --- a/gr-trellis/src/examples/python/test_tcm_combined.py +++ b/gr-trellis/src/examples/python/test_tcm_combined.py @@ -18,7 +18,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): src_head = gr.head (gr.sizeof_short,Kb/16) # packet size in shorts s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL diff --git a/gr-trellis/src/examples/python/test_tcm_parallel.py b/gr-trellis/src/examples/python/test_tcm_parallel.py index 0372351aad..72fb8cf3bf 100755 --- a/gr-trellis/src/examples/python/test_tcm_parallel.py +++ b/gr-trellis/src/examples/python/test_tcm_parallel.py @@ -19,7 +19,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed,P): s2fsmi=gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality s2p = gr.stream_to_streams(gr.sizeof_short,P) # serial to parallel enc = trellis.encoder_ss(f,0) # initiali state = 0 - mod = gr.chunks_to_symbols_sf(constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add=[] diff --git a/gr-trellis/src/examples/python/test_turbo_equalization.py b/gr-trellis/src/examples/python/test_turbo_equalization.py index 18bfb022a9..d97f3f2c29 100755 --- a/gr-trellis/src/examples/python/test_turbo_equalization.py +++ b/gr-trellis/src/examples/python/test_turbo_equalization.py @@ -59,7 +59,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,dimensionality,tot_constellat inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) enc_in = trellis.encoder_ss(fi,0) # initial state = 0 # essentially here we implement the combination of modulation and channel as a memoryless modulation (the memory induced by the channel is hidden in the innner FSM) - mod = gr.chunks_to_symbols_sf(tot_constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(tot_constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_turbo_equalization1.py b/gr-trellis/src/examples/python/test_turbo_equalization1.py index 17ad430235..da1132d38c 100755 --- a/gr-trellis/src/examples/python/test_turbo_equalization1.py +++ b/gr-trellis/src/examples/python/test_turbo_equalization1.py @@ -61,7 +61,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensiona src = gr.vector_source_s(packet,False) enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/examples/python/test_turbo_equalization2.py b/gr-trellis/src/examples/python/test_turbo_equalization2.py index 5a6c77e9d4..886240efac 100755 --- a/gr-trellis/src/examples/python/test_turbo_equalization2.py +++ b/gr-trellis/src/examples/python/test_turbo_equalization2.py @@ -59,7 +59,7 @@ def run_test (fo,fi,interleaver,Kb,bitspersymbol,K,channel,modulation,dimensiona src = gr.vector_source_s(packet,False) enc_out = trellis.encoder_ss(fo,0) # initial state = 0 inter = trellis.permutation(interleaver.K(),interleaver.INTER(),1,gr.sizeof_short) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/examples/python/test_viterbi_equalization.py b/gr-trellis/src/examples/python/test_viterbi_equalization.py index 9f3f7e3911..00d54620b2 100755 --- a/gr-trellis/src/examples/python/test_viterbi_equalization.py +++ b/gr-trellis/src/examples/python/test_viterbi_equalization.py @@ -16,7 +16,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,tot_constellation,N0,seed): s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 # essentially here we implement the combination of modulation and channel as a memoryless modulation (the memory induced by the channel is hidden in the FSM) - mod = gr.chunks_to_symbols_sf(tot_constellation,dimensionality) + mod = digital.chunks_to_symbols_sf(tot_constellation,dimensionality) # CHANNEL add = gr.add_ff() diff --git a/gr-trellis/src/examples/python/test_viterbi_equalization1.py b/gr-trellis/src/examples/python/test_viterbi_equalization1.py index 90eb4790e5..caf99ff581 100755 --- a/gr-trellis/src/examples/python/test_viterbi_equalization1.py +++ b/gr-trellis/src/examples/python/test_viterbi_equalization1.py @@ -22,7 +22,7 @@ def run_test (f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constel packet[i] = 0 packet[len(packet)-i-1] = 0 src = gr.vector_source_s(packet,False) - mod = gr.chunks_to_symbols_sf(modulation[1],modulation[0]) + mod = digital.chunks_to_symbols_sf(modulation[1],modulation[0]) # CHANNEL isi = gr.fir_filter_fff(1,channel) diff --git a/gr-trellis/src/python/qa_trellis.py b/gr-trellis/src/python/qa_trellis.py index fcc651ec6d..935459a3c7 100755 --- a/gr-trellis/src/python/qa_trellis.py +++ b/gr-trellis/src/python/qa_trellis.py @@ -114,7 +114,7 @@ class trellis_tb(gr.top_block): s2fsmi = gr.packed_to_unpacked_ss(bitspersymbol, gr.GR_MSB_FIRST) # initial FSM state = 0 enc = trellis.encoder_ss(f, 0) - mod = gr.chunks_to_symbols_sc(constellation.points(), 1) + mod = digital_swig.chunks_to_symbols_sc(constellation.points(), 1) # CHANNEL add = gr.add_cc() diff --git a/gr-uhd/gnuradio-uhd.pc.in b/gr-uhd/gnuradio-uhd.pc.in index 383ad6011b..721141c520 100644 --- a/gr-uhd/gnuradio-uhd.pc.in +++ b/gr-uhd/gnuradio-uhd.pc.in @@ -3,7 +3,7 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ -Name: gnuradio-qtgui +Name: gnuradio-uhd Description: GNU Radio blocks for UHD Requires: gnuradio-core Version: @LIBVER@ diff --git a/gr-wavelet/lib/CMakeLists.txt b/gr-wavelet/lib/CMakeLists.txt index 76da7e5347..2d4382b765 100644 --- a/gr-wavelet/lib/CMakeLists.txt +++ b/gr-wavelet/lib/CMakeLists.txt @@ -21,20 +21,18 @@ # Setup the include and linker paths ######################################################################## include_directories( - ${GNURADIO_CORE_INCLUDE_DIRS} ${GR_WAVELET_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ${GNURADIO_CORE_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${GSL_INCLUDE_DIRS} ) -include_directories(${WAVELET_INCLUDE_DIRS}) link_directories(${WAVELET_LIBRARY_DIRS}) - -include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) - -include_directories(${GSL_INCLUDE_DIRS}) link_directories(${GSL_LIBRARY_DIRS}) +add_definitions(${GSL_DEFINITIONS}) ######################################################################## # Setup library diff --git a/gr-wavelet/python/CMakeLists.txt b/gr-wavelet/python/CMakeLists.txt index 650299672e..f118683954 100644 --- a/gr-wavelet/python/CMakeLists.txt +++ b/gr-wavelet/python/CMakeLists.txt @@ -41,7 +41,7 @@ foreach(py_qa_test_file ${py_qa_test_files}) ${CMAKE_BINARY_DIR}/gr-wavelet/python ${CMAKE_BINARY_DIR}/gr-wavelet/swig ) - set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-wavelet) - GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${py_qa_test_file}) + set(GR_TEST_TARGET_DEPS volk gruel gnuradio-core gnuradio-wavelet) + GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-wavelet/swig/CMakeLists.txt b/gr-wavelet/swig/CMakeLists.txt index 82d083dea2..2c5f433ebb 100644 --- a/gr-wavelet/swig/CMakeLists.txt +++ b/gr-wavelet/swig/CMakeLists.txt @@ -30,7 +30,7 @@ set(GR_SWIG_INCLUDE_DIRS ) set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/wavelet_swig_doc.i) -set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../lib) +set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/wavelet) set(GR_SWIG_LIBRARIES gnuradio-wavelet ${GSL_LDFLAGS}) diff --git a/gr-wxgui/CMakeLists.txt b/gr-wxgui/CMakeLists.txt index 0fc26dee1c..8150c7d802 100644 --- a/gr-wxgui/CMakeLists.txt +++ b/gr-wxgui/CMakeLists.txt @@ -76,7 +76,7 @@ install( ######################################################################## install( FILES ${CMAKE_CURRENT_SOURCE_DIR}/gr-wxgui.conf - DESTINATION ${GR_PKG_CONF_DIR} + DESTINATION ${GR_PREFSDIR} COMPONENT "wxgui" ) diff --git a/gr-wxgui/grc/wxgui_fftsink2.xml b/gr-wxgui/grc/wxgui_fftsink2.xml index ec5501838a..74ee5b173e 100644 --- a/gr-wxgui/grc/wxgui_fftsink2.xml +++ b/gr-wxgui/grc/wxgui_fftsink2.xml @@ -36,6 +36,12 @@ fftsink2.$(type.fcn)( $(parent).Add(self.$(id).win) #else $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos())))) +#end if +#if $freqvar() is not None +def $(id)_callback(x, y): + self.set_$(freqvar)(x) + +self.$(id).set_callback($(id)_callback) #end if</make> <callback>set_baseband_freq($baseband_freq)</callback> <callback>set_sample_rate($samp_rate)</callback> @@ -216,6 +222,12 @@ $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos())))) <value></value> <type>notebook</type> </param> + <param> + <name>Freq Set Varname</name> + <key>freqvar</key> + <value>None</value> + <type>raw</type> + </param> <check>not $win_size or len($win_size) == 2</check> <sink> <name>in</name> diff --git a/gr-wxgui/grc/wxgui_waterfallsink2.xml b/gr-wxgui/grc/wxgui_waterfallsink2.xml index da6a8a3d1a..8921e87f9a 100644 --- a/gr-wxgui/grc/wxgui_waterfallsink2.xml +++ b/gr-wxgui/grc/wxgui_waterfallsink2.xml @@ -34,6 +34,12 @@ waterfallsink2.$(type.fcn)( $(parent).Add(self.$(id).win) #else $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos())))) +#end if +#if $freqvar() is not None +def $(id)_callback(x, y): + self.set_$(freqvar)(x) + +self.$(id).set_callback($(id)_callback) #end if</make> <callback>set_baseband_freq($baseband_freq)</callback> <callback>set_sample_rate($samp_rate)</callback> @@ -173,6 +179,12 @@ $(parent).GridAdd(self.$(id).win, $(', '.join(map(str, $grid_pos())))) <value></value> <type>notebook</type> </param> + <param> + <name>Freq Set Varname</name> + <key>freqvar</key> + <value>None</value> + <type>raw</type> + </param> <check>not $win_size or len($win_size) == 2</check> <sink> <name>in</name> diff --git a/gr-wxgui/src/python/fft_window.py b/gr-wxgui/src/python/fft_window.py index 99c1cf6e1a..fac83a4a34 100644 --- a/gr-wxgui/src/python/fft_window.py +++ b/gr-wxgui/src/python/fft_window.py @@ -300,6 +300,8 @@ class fft_window(wx.Panel, pubsub.pubsub): #initial update self.update_grid() + def set_callback(self,callb): + self.plotter.set_callback(callb) def autoscale(self, *args): """ diff --git a/gr-wxgui/src/python/fftsink_gl.py b/gr-wxgui/src/python/fftsink_gl.py index 6b268f6cb2..dc31e84a10 100644 --- a/gr-wxgui/src/python/fftsink_gl.py +++ b/gr-wxgui/src/python/fftsink_gl.py @@ -127,6 +127,9 @@ class _fft_sink_base(gr.hier_block2, common.wxgui_hb): setattr(self.win, 'set_peak_hold', getattr(self, 'set_peak_hold')) #BACKWARDS #connect self.wxgui_connect(self, fft, sink) + + def set_callback(self,callb): + self.win.set_callback(callb) class fft_sink_f(_fft_sink_base): _fft_chain = blks2.logpwrfft_f diff --git a/gr-wxgui/src/python/plotter/channel_plotter.py b/gr-wxgui/src/python/plotter/channel_plotter.py index a3a2b64519..4bcc36fd4c 100644 --- a/gr-wxgui/src/python/plotter/channel_plotter.py +++ b/gr-wxgui/src/python/plotter/channel_plotter.py @@ -56,6 +56,7 @@ class channel_plotter(grid_plotter_base): self._channels = dict() #init channel plotter self.register_init(self._init_channel_plotter) + self.callback = None def _init_channel_plotter(self): """ @@ -150,6 +151,13 @@ class channel_plotter(grid_plotter_base): label_str += '\n%s: %s'%(channel, common.eng_format(y_value, self.y_units)) return label_str + def _call_callback (self, x_val, y_val): + if self.callback != None: + self.callback(x_val, y_val) + + def set_callback (self, callback): + self.callback = callback + def _draw_legend(self): """ Draw the legend in the upper right corner. diff --git a/gr-wxgui/src/python/plotter/common.py b/gr-wxgui/src/python/plotter/common.py index 6775b70571..88215e039a 100644 --- a/gr-wxgui/src/python/plotter/common.py +++ b/gr-wxgui/src/python/plotter/common.py @@ -103,6 +103,7 @@ class point_label_thread(threading.Thread, mutex): self._plotter.Bind(wx.EVT_MOTION, lambda evt: self.enqueue(evt.GetPosition())) self._plotter.Bind(wx.EVT_LEAVE_WINDOW, lambda evt: self.enqueue(None)) self._plotter.Bind(wx.EVT_RIGHT_DOWN, lambda evt: plotter.enable_point_label(not plotter.enable_point_label())) + self._plotter.Bind(wx.EVT_LEFT_DOWN, lambda evt: plotter.call_freq_callback(evt.GetPosition())) #start the thread threading.Thread.__init__(self) self.start() diff --git a/gr-wxgui/src/python/plotter/grid_plotter_base.py b/gr-wxgui/src/python/plotter/grid_plotter_base.py index 5eaa76bc0e..f1bc8f546d 100644 --- a/gr-wxgui/src/python/plotter/grid_plotter_base.py +++ b/gr-wxgui/src/python/plotter/grid_plotter_base.py @@ -85,7 +85,19 @@ class grid_plotter_base(plotter_base): self._point_label_cache.changed(True) self.update() self.unlock() - + + def call_freq_callback(self, coor): + x, y = self._point_label_coordinate + if x < self.padding_left or x > self.width-self.padding_right: return + if y < self.padding_top or y > self.height-self.padding_bottom: return + #scale to window bounds + x_win_scalar = float(x - self.padding_left)/(self.width-self.padding_left-self.padding_right) + y_win_scalar = float((self.height - y) - self.padding_bottom)/(self.height-self.padding_top-self.padding_bottom) + #scale to grid bounds + x_val = x_win_scalar*(self.x_max-self.x_min) + self.x_min + y_val = y_win_scalar*(self.y_max-self.y_min) + self.y_min + self._call_callback(x_val, y_val) + def enable_grid_aspect_ratio(self, enable=None): """ Enable/disable the grid aspect ratio. diff --git a/gr-wxgui/src/python/plotter/plotter_base.py b/gr-wxgui/src/python/plotter/plotter_base.py index 5af5803392..2fdd0f20ab 100644 --- a/gr-wxgui/src/python/plotter/plotter_base.py +++ b/gr-wxgui/src/python/plotter/plotter_base.py @@ -189,7 +189,10 @@ class plotter_base(wx.glcanvas.GLCanvas, common.mutex): if self.use_persistence: if self.clear_accum: #GL.glClear(GL.GL_ACCUM_BUFFER_BIT) - GL.glAccum(GL.GL_LOAD, 1.0) + try: + GL.glAccum(GL.GL_LOAD, 1.0) + except: + pass self.clear_accum=False GL.glAccum(GL.GL_MULT, 1.0-self.persist_alpha) diff --git a/gr-wxgui/src/python/plotter/waterfall_plotter.py b/gr-wxgui/src/python/plotter/waterfall_plotter.py index f2456241c0..6a6bf6330e 100644 --- a/gr-wxgui/src/python/plotter/waterfall_plotter.py +++ b/gr-wxgui/src/python/plotter/waterfall_plotter.py @@ -110,6 +110,7 @@ class waterfall_plotter(grid_plotter_base): self._counter = 0 self.set_num_lines(0) self.set_color_mode(COLORS.keys()[0]) + self.callback = None def _init_waterfall(self): """ @@ -172,6 +173,13 @@ class waterfall_plotter(grid_plotter_base): """ return '%s: %s'%(self.x_label, common.eng_format(x_val, self.x_units)) + def _call_callback(self, x_val, y_val): + if self.callback != None: + self.callback(x_val,y_val) + + def set_callback(self,callback): + self.callback = callback + def _draw_legend(self): """ Draw the color scale legend. diff --git a/gr-wxgui/src/python/waterfall_window.py b/gr-wxgui/src/python/waterfall_window.py index c78244f042..cd60104d7a 100644 --- a/gr-wxgui/src/python/waterfall_window.py +++ b/gr-wxgui/src/python/waterfall_window.py @@ -238,6 +238,9 @@ class waterfall_window(wx.Panel, pubsub.pubsub): #initial update self.update_grid() + def set_callback(self,callb): + self.plotter.set_callback(callb) + def autoscale(self, *args): """ Autoscale the waterfall plot to the last frame. diff --git a/gr-wxgui/src/python/waterfallsink_gl.py b/gr-wxgui/src/python/waterfallsink_gl.py index c2c4e8df7a..b69c5dda0c 100644 --- a/gr-wxgui/src/python/waterfallsink_gl.py +++ b/gr-wxgui/src/python/waterfallsink_gl.py @@ -113,6 +113,9 @@ class _waterfall_sink_base(gr.hier_block2, common.wxgui_hb): #connect self.wxgui_connect(self, fft, sink) + def set_callback(self,callb): + self.win.set_callback(callb) + class waterfall_sink_f(_waterfall_sink_base): _fft_chain = blks2.logpwrfft_f _item_size = gr.sizeof_float diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index f54aa4f809..219bbe1642 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -75,7 +75,7 @@ configure_file( install( FILES ${CMAKE_CURRENT_BINARY_DIR}/grc.conf - DESTINATION ${GR_PKG_CONF_DIR} + DESTINATION ${GR_PREFSDIR} COMPONENT "grc" ) diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml index 18bc050bac..2377679b65 100644 --- a/grc/blocks/block_tree.xml +++ b/grc/blocks/block_tree.xml @@ -13,7 +13,6 @@ <block>gr_noise_source_x</block> <block>gr_vector_source_x</block> <block>random_source_x</block> - <block>gr_glfsr_source_x</block> <block>gr_null_source</block> <block>gr_file_source</block> <block>blks2_tcp_source</block> @@ -34,6 +33,7 @@ <block>gr_message_sink</block> <block>pad_sink</block> <block>virtual_sink</block> + <block>gr_tag_debug</block> </cat> <cat> <name>Operators</name> @@ -61,6 +61,7 @@ <block>gr_fft_vxx</block> <block>blks2_logpwrfft_x</block> + <block>gr_vector_insert_x</block> </cat> <cat> <name>Type Conversions</name> @@ -114,8 +115,7 @@ <block>gr_unpacked_to_packed_xx</block> <block>gr_packed_to_unpacked_xx</block> <block>gr_unpack_k_bits_bb</block> - <block>gr_chunks_to_symbols_xx</block> - <block>gr_map_bb</block> + <block>gr_pack_k_bits_bb</block> </cat> <cat> <name>Synchronizers</name> @@ -127,9 +127,7 @@ <block>gr_pll_freqdet_cf</block> <block>gr_pll_refout_cc</block> - <block>gr_pn_correlator_cc</block> <block>gr_simple_correlator</block> - <block>gr_simple_framer</block> <block>blks2_packet_decoder</block> <block>blks2_packet_encoder</block> @@ -183,6 +181,7 @@ <block>blks2_rational_resampler_xxx</block> <block>gr_fractional_interpolator_xx</block> <block>gr_keep_one_in_n</block> + <block>gr_keep_m_in_n</block> <block>gr_moving_average_xx</block> <block>gr_iqcomp_cc</block> <block>gr_dc_blocker</block> @@ -195,11 +194,6 @@ <block>gr_quadrature_demod_cf</block> <block>gr_cpfsk_bc</block> - <block>gr_diff_phasor_cc</block> - - <block>gr_diff_encoder_bb</block> - <block>gr_diff_decoder_bb</block> - <block>blks2_wfm_tx</block> <block>blks2_wfm_rcv</block> <block>blks2_wfm_rcv_pll</block> @@ -222,15 +216,8 @@ <block>gr_decode_ccsds_27_fb</block> </cat> <cat> - <name>Line Coding</name> - <block>gr_scrambler_bb</block> - <block>gr_descrambler_bb</block> - <block>gr_additive_scrambler_bb</block> - </cat> - <cat> <name>Probes</name> <block>gr_probe_avg_mag_sqrd_x</block> - <block>gr_probe_density_b</block> <block>gr_probe_signal_f</block> </cat> <cat> diff --git a/grc/blocks/gr_additive_scrambler_bb.xml b/grc/blocks/gr_additive_scrambler_bb.xml deleted file mode 100644 index a15d6eefbe..0000000000 --- a/grc/blocks/gr_additive_scrambler_bb.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -## Additive Scrambler -################################################### - --> -<block> - <name>Additive Scrambler</name> - <key>gr_additive_scrambler_bb</key> - <import>from gnuradio import gr</import> - <make>gr.additive_scrambler_bb($mask, $seed, $len, $count)</make> - <param> - <name>Mask</name> - <key>mask</key> - <value>0x8A</value> - <type>hex</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <value>0x7F</value> - <type>hex</type> - </param> - <param> - <name>Length</name> - <key>len</key> - <value>7</value> - <type>int</type> - </param> - <param> - <name>Count</name> - <key>count</key> - <value>0</value> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_chunks_to_symbols.xml b/grc/blocks/gr_chunks_to_symbols.xml deleted file mode 100644 index e9da38e9a5..0000000000 --- a/grc/blocks/gr_chunks_to_symbols.xml +++ /dev/null @@ -1,77 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Chunks to Symbols -################################################### - --> -<block> - <name>Chunks to Symbols</name> - <key>gr_chunks_to_symbols_xx</key> - <import>from gnuradio import gr</import> - <make>gr.chunks_to_symbols_$(in_type.fcn)$(out_type.fcn)($symbol_table, $dimension)</make> - <param> - <name>Input Type</name> - <key>in_type</key> - <type>enum</type> - <option> - <name>Int</name> - <key>int</key> - <opt>fcn:i</opt> - </option> - <option> - <name>Short</name> - <key>short</key> - <opt>fcn:s</opt> - </option> - <option> - <name>Byte</name> - <key>byte</key> - <opt>fcn:b</opt> - </option> - </param> - <param> - <name>Output Type</name> - <key>out_type</key> - <type>enum</type> - <option> - <name>Complex</name> - <key>complex</key> - <opt>fcn:c</opt> - <opt>table:complex_vector</opt> - </option> - <option> - <name>Float</name> - <key>float</key> - <opt>fcn:f</opt> - <opt>table:real_vector</opt> - </option> - </param> - <param> - <name>Symbol Table</name> - <key>symbol_table</key> - <type>$out_type.table</type> - </param> - <param> - <name>Dimension</name> - <key>dimension</key> - <value>2</value> - <type>int</type> - </param> - <param> - <name>Num Ports</name> - <key>num_ports</key> - <value>1</value> - <type>int</type> - </param> - <check>$num_ports > 0</check> - <sink> - <name>in</name> - <type>$in_type</type> - <nports>$num_ports</nports> - </sink> - <source> - <name>out</name> - <type>$out_type</type> - <nports>$num_ports</nports> - </source> -</block> diff --git a/grc/blocks/gr_descrambler_bb.xml b/grc/blocks/gr_descrambler_bb.xml deleted file mode 100644 index 5cfbcc203e..0000000000 --- a/grc/blocks/gr_descrambler_bb.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Descrambler -################################################### - --> -<block> - <name>Descrambler</name> - <key>gr_descrambler_bb</key> - <import>from gnuradio import gr</import> - <make>gr.descrambler_bb($mask, $seed, $len)</make> - <param> - <name>Mask</name> - <key>mask</key> - <value>0x8A</value> - <type>hex</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <value>0x7F</value> - <type>hex</type> - </param> - <param> - <name>Length</name> - <key>len</key> - <value>7</value> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_diff_phasor_cc.xml b/grc/blocks/gr_diff_phasor_cc.xml deleted file mode 100644 index 2b2d7e372c..0000000000 --- a/grc/blocks/gr_diff_phasor_cc.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Differential Phasor -################################################### - --> -<block> - <name>Differential Phasor</name> - <key>gr_diff_phasor_cc</key> - <import>from gnuradio import gr</import> - <make>gr.diff_phasor_cc()</make> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/gr_glfsr_source_x.xml b/grc/blocks/gr_glfsr_source_x.xml deleted file mode 100644 index 88fb66797b..0000000000 --- a/grc/blocks/gr_glfsr_source_x.xml +++ /dev/null @@ -1,59 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##GLFSR Source -################################################### - --> -<block> - <name>GLFSR Source</name> - <key>gr_glfsr_source_x</key> - <import>from gnuradio import gr</import> - <make>gr.glfsr_source_$(type.fcn)($degree, $repeat, $mask, $seed)</make> - <param> - <name>Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>Float</name> - <key>float</key> - <opt>fcn:f</opt> - </option> - <option> - <name>Byte</name> - <key>byte</key> - <opt>fcn:b</opt> - </option> - </param> - <param> - <name>Degree</name> - <key>degree</key> - <type>int</type> - </param> - <param> - <name>Repeat</name> - <key>repeat</key> - <type>enum</type> - <option> - <name>Yes</name> - <key>True</key> - </option> - <option> - <name>No</name> - <key>False</key> - </option> - </param> - <param> - <name>Mask</name> - <key>mask</key> - <type>int</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <type>int</type> - </param> - <source> - <name>out</name> - <type>$type</type> - </source> -</block> diff --git a/grc/blocks/gr_keep_m_in_n.xml b/grc/blocks/gr_keep_m_in_n.xml new file mode 100644 index 0000000000..35a1561764 --- /dev/null +++ b/grc/blocks/gr_keep_m_in_n.xml @@ -0,0 +1,76 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Keep M in N +################################################### + --> +<block> + <name>Keep M in N</name> + <key>gr_keep_m_in_n</key> + <import>from gnuradio import gr</import> + <make>gr.keep_m_in_n($type.size, $m, $n, $offset)</make> + <callback>set_offset($offset)</callback> + <callback>set_m($m)</callback> + <callback>set_n($n)</callback> + <param> + <name>Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>M</name> + <key>m</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>N</name> + <key>n</key> + <value>2</value> + <type>int</type> + </param> + <param> + <name>initial offset</name> + <key>offset</key> + <value>0</value> + <type>int</type> + </param> + <check>$n > 0</check> + <check>$m > 0</check> + <check>$m < $n</check> + <sink> + <name>in</name> + <type>$type</type> + <vlen>1</vlen> + </sink> + <source> + <name>out</name> + <type>$type</type> + <vlen>1</vlen> + </source> +</block> diff --git a/grc/blocks/gr_map_bb.xml b/grc/blocks/gr_map_bb.xml deleted file mode 100644 index 20d6bd2b44..0000000000 --- a/grc/blocks/gr_map_bb.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Map -################################################### - --> -<block> - <name>Map</name> - <key>gr_map_bb</key> - <import>from gnuradio import gr</import> - <make>gr.map_bb($map)</make> - <param> - <name>Map</name> - <key>map</key> - <type>int_vector</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_diff_encoder_bb.xml b/grc/blocks/gr_pack_k_bits_bb.xml index 21241eac22..34e64a5d96 100644 --- a/grc/blocks/gr_diff_encoder_bb.xml +++ b/grc/blocks/gr_pack_k_bits_bb.xml @@ -1,17 +1,17 @@ <?xml version="1.0"?> <!-- ################################################### -##Differential Encoder +##Pack K Bits ################################################### --> <block> - <name>Differential Encoder</name> - <key>gr_diff_encoder_bb</key> + <name>Pack K Bits</name> + <key>gr_pack_k_bits_bb</key> <import>from gnuradio import gr</import> - <make>gr.diff_encoder_bb($modulus)</make> + <make>gr.pack_k_bits_bb($k)</make> <param> - <name>Modulus</name> - <key>modulus</key> + <name>K</name> + <key>k</key> <type>int</type> </param> <sink> @@ -22,4 +22,9 @@ <name>out</name> <type>byte</type> </source> + + <doc> + Pack K unpacked bits (one bit per byte) into a single packed byte containing k bits and 8 - k zeros. + </doc> + </block> diff --git a/grc/blocks/gr_pn_correlator_cc.xml b/grc/blocks/gr_pn_correlator_cc.xml deleted file mode 100644 index 094f46cdfd..0000000000 --- a/grc/blocks/gr_pn_correlator_cc.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##PN Correlator -################################################### - --> -<block> - <name>PN Correlator</name> - <key>gr_pn_correlator_cc</key> - <import>from gnuradio import gr</import> - <make>gr.pn_correlator_cc($degree, $mask, $seed)</make> - <param> - <name>Degree</name> - <key>degree</key> - <type>int</type> - </param> - <param> - <name>Mask</name> - <key>mask</key> - <type>int</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>complex</type> - </sink> - <source> - <name>out</name> - <type>complex</type> - </source> -</block> diff --git a/grc/blocks/gr_probe_density_b.xml b/grc/blocks/gr_probe_density_b.xml deleted file mode 100644 index 3a91256aa5..0000000000 --- a/grc/blocks/gr_probe_density_b.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Probe Density -################################################### - --> -<block> - <name>Probe Density</name> - <key>gr_probe_density_b</key> - <import>from gnuradio import gr</import> - <make>gr.probe_density_b($alpha)</make> - <callback>set_alpha($alpha)</callback> - <param> - <name>Alpha</name> - <key>alpha</key> - <value>1</value> - <type>real</type> - </param> - <param> - <name>Probe Rate</name> - <key>probe_rate</key> - <value>10</value> - <type>real</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <doc> -Available functions to probe: density() - -Use with the function probe block. - </doc> -</block> diff --git a/grc/blocks/gr_scrambler_bb.xml b/grc/blocks/gr_scrambler_bb.xml deleted file mode 100644 index d079c4015f..0000000000 --- a/grc/blocks/gr_scrambler_bb.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Descrambler -################################################### - --> -<block> - <name>Scrambler</name> - <key>gr_scrambler_bb</key> - <import>from gnuradio import gr</import> - <make>gr.scrambler_bb($mask, $seed, $len)</make> - <param> - <name>Mask</name> - <key>mask</key> - <value>0x8A</value> - <type>hex</type> - </param> - <param> - <name>Seed</name> - <key>seed</key> - <value>0x7F</value> - <type>hex</type> - </param> - <param> - <name>Length</name> - <key>len</key> - <value>7</value> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_simple_framer.xml b/grc/blocks/gr_simple_framer.xml deleted file mode 100644 index 2a0295c417..0000000000 --- a/grc/blocks/gr_simple_framer.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Simple Framer -################################################### - --> -<block> - <name>Simple Framer</name> - <key>gr_simple_framer</key> - <import>from gnuradio import gr</import> - <make>gr.simple_framer($payload_bytesize)</make> - <param> - <name>Payload Byte Size</name> - <key>payload_bytesize</key> - <type>int</type> - </param> - <sink> - <name>in</name> - <type>byte</type> - </sink> - <source> - <name>out</name> - <type>byte</type> - </source> -</block> diff --git a/grc/blocks/gr_tag_debug.xml b/grc/blocks/gr_tag_debug.xml new file mode 100644 index 0000000000..4af7729be9 --- /dev/null +++ b/grc/blocks/gr_tag_debug.xml @@ -0,0 +1,82 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Tag Debug +################################################### + --> +<block> + <name>Tag Debug</name> + <key>gr_tag_debug</key> + <import>from gnuradio import gr</import> + <make>gr.tag_debug($type.size*$vlen, $name)</make> + <callback>set_display($display)</callback> + <param> + <name>Input Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>size:gr.sizeof_gr_complex</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>size:gr.sizeof_float</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>size:gr.sizeof_int</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>size:gr.sizeof_short</opt> + </option> + <option> + <name>Byte</name> + <key>byte</key> + <opt>size:gr.sizeof_char</opt> + </option> + </param> + <param> + <name>Name</name> + <key>name</key> + <type>string</type> + </param> + <param> + <name>Num Inputs</name> + <key>num_inputs</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Vec Length</name> + <key>vlen</key> + <value>1</value> + <type>int</type> + </param> + <param> + <name>Display</name> + <key>display</key> + <value>True</value> + <type>bool</type> + <option> + <name>On</name> + <key>True</key> + </option> + <option> + <name>Off</name> + <key>False</key> + </option> + </param> + <check>$num_inputs >= 1</check> + <check>$vlen > 0</check> + <sink> + <name>in</name> + <type>$type</type> + <vlen>$vlen</vlen> + <nports>$num_inputs</nports> + </sink> +</block> diff --git a/grc/blocks/gr_vector_insert_x.xml b/grc/blocks/gr_vector_insert_x.xml new file mode 100644 index 0000000000..f9ce1f6544 --- /dev/null +++ b/grc/blocks/gr_vector_insert_x.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Vector Source +################################################### + --> +<block> + <name>Vector Insert</name> + <key>gr_vector_insert_x</key> + <import>from gnuradio import gr</import> + <make>gr.vector_insert_$(type.fcn)($vector, $period, $offset)</make> + <param> + <name>Output Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Byte</name> + <key>byte</key> + <opt>fcn:b</opt> + <opt>vec_type:int_vector</opt> + </option> + <option> + <name>Complex</name> + <key>complex</key> + <opt>fcn:c</opt> + <opt>vec_type:complex_vector</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>fcn:f</opt> + <opt>vec_type:real_vector</opt> + </option> + <option> + <name>Int</name> + <key>int</key> + <opt>fcn:i</opt> + <opt>vec_type:int_vector</opt> + </option> + <option> + <name>Short</name> + <key>short</key> + <opt>fcn:s</opt> + <opt>vec_type:int_vector</opt> + </option> + </param> + <param> + <name>Vector</name> + <key>vector</key> + <value>0, 0, 0</value> + <type>$type.vec_type</type> + </param> + <param> + <name>Periodicity</name> + <key>period</key> + <value>100</value> + <type>int</type> + </param> + <param> + <name>Offset</name> + <key>offset</key> + <value>0</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + </sink> + <source> + <name>out</name> + <type>$type</type> + </source> + + <doc> + Periodicity, the length of the periodicity at which the vector should be inserted at the output. + (i.e. one vector for every N output items) + + Offset sepcifies where in the cycle period we should begin at. + </doc> +</block> diff --git a/grc/grc_gnuradio/blks2/packet.py b/grc/grc_gnuradio/blks2/packet.py index e39f55c841..494afa986a 100644 --- a/grc/grc_gnuradio/blks2/packet.py +++ b/grc/grc_gnuradio/blks2/packet.py @@ -1,4 +1,4 @@ -# Copyright 2008, 2009 Free Software Foundation, Inc. +# Copyright 2008, 2009, 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -158,7 +158,7 @@ class packet_decoder(gr.hier_block2): #blocks msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY correlator = digital.correlate_access_code_bb(self._access_code, self._threshold) - framer_sink = gr.framer_sink_1(msgq) + framer_sink = digital.framer_sink_1(msgq) #initialize hier2 gr.hier_block2.__init__( self, diff --git a/grc/python/Port.py b/grc/python/Port.py index d0ef51b483..9f8b50d052 100644 --- a/grc/python/Port.py +++ b/grc/python/Port.py @@ -139,6 +139,10 @@ class Port(_Port, _GUIPort): self._type = '' self._vlen = '' + def resolve_virtual_source(self): + if self.get_parent().is_virtual_sink(): return _get_source_from_virtual_sink_port(self) + if self.get_parent().is_virtual_source(): return _get_source_from_virtual_source_port(self) + def resolve_empty_type(self): if self.is_sink(): try: diff --git a/gruel/src/include/gruel/CMakeLists.txt b/gruel/src/include/gruel/CMakeLists.txt index 9818f1c09c..d4c36eddbb 100644 --- a/gruel/src/include/gruel/CMakeLists.txt +++ b/gruel/src/include/gruel/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. +# Copyright 2010-2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -18,30 +18,12 @@ # Boston, MA 02110-1301, USA. ######################################################################## -# Generate inet.h header file -######################################################################## -include(TestBigEndian) -enable_language(C) -TEST_BIG_ENDIAN(GR_ARCH_BIGENDIAN) - -include(CheckIncludeFileCXX) -CHECK_INCLUDE_FILE_CXX(byteswap.h GR_HAVE_BYTESWAP) -CHECK_INCLUDE_FILE_CXX(arpa/inet.h GR_HAVE_ARPA_INET) -CHECK_INCLUDE_FILE_CXX(netinet/in.h GR_HAVE_NETINET_IN) - -configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/inet.h.in - ${CMAKE_CURRENT_BINARY_DIR}/inet.h -@ONLY) - -######################################################################## # Install the headers ######################################################################## install(FILES api.h attributes.h high_res_timer.h - ${CMAKE_CURRENT_BINARY_DIR}/inet.h msg_accepter.h msg_accepter_msgq.h msg_queue.h diff --git a/gruel/src/include/gruel/inet.h.in b/gruel/src/include/gruel/inet.h.in deleted file mode 100644 index 74f14bd923..0000000000 --- a/gruel/src/include/gruel/inet.h.in +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008, 2009 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef INCLUDED_INET_H -#define INCLUDED_INET_H - -#include <gruel/api.h> -#include <stdint.h> - -#if 1 /* missing htonll or ntohll */ -#if @GR_ARCH_BIGENDIAN@ /* GR_ARCH_BIGENDIAN */ -// Nothing to do... -static inline uint64_t htonll(uint64_t x){ return x;} -static inline uint64_t ntohll(uint64_t x){ return x;} -#else -#if @GR_HAVE_BYTESWAP@ /* GR_HAVE_BYTESWAP */ -#include <byteswap.h> -#else - -static inline uint64_t -bswap_64(uint64_t x) -{ - return ((x & 0x00000000000000ffull) << 56) | ((x & 0x000000000000ff00ull) << 40) | - ((x & 0x0000000000ff0000ull) << 24) | ((x & 0x00000000ff000000ull) << 8) | - ((x & 0x000000ff00000000ull) >> 8) | ((x & 0x0000ff0000000000ull) >> 24) | - ((x & 0x00ff000000000000ull) >> 40) | ((x & 0xff00000000000000ull) >> 56); -} - -#endif /* GR_HAVE_BYTESWAP */ - -static inline uint64_t htonll(uint64_t x){ return bswap_64(x);} -static inline uint64_t ntohll(uint64_t x){ return bswap_64(x);} - -#endif /* GR_ARCH_BIGENDIAN */ -#endif /* missing htonll or ntohll */ - -#if @GR_HAVE_ARPA_INET@ /* GR_HAVE_ARPA_INET */ -#include <arpa/inet.h> -#elif @GR_HAVE_NETINET_IN@ /* GR_HAVE_NETINET_IN */ -#include <netinet/in.h> -#else -#include <stdint.h> - -#if @GR_ARCH_BIGENDIAN@ /* GR_ARCH_BIGENDIAN */ -// Nothing to do... -static inline uint32_t htonl(uint32_t x){ return x; } -static inline uint16_t htons(uint16_t x){ return x; } -static inline uint32_t ntohl(uint32_t x){ return x; } -static inline uint16_t ntohs(uint16_t x){ return x; } -#else -#if @GR_HAVE_BYTESWAP@ /* GR_HAVE_BYTESWAP */ -#include <byteswap.h> -#else -static inline uint16_t -bswap_16 (uint16_t x) -{ - return ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)); -} - -static inline uint32_t -bswap_32 (uint32_t x) -{ - return ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) \ - | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)); -} -#endif /* GR_HAVE_BYTESWAP */ - -static inline uint32_t htonl(uint32_t x){ return bswap_32(x); } -static inline uint16_t htons(uint16_t x){ return bswap_16(x); } -static inline uint32_t ntohl(uint32_t x){ return bswap_32(x); } -static inline uint16_t ntohs(uint16_t x){ return bswap_16(x); } -#endif /* GR_ARCH_BIGENDIAN */ - -#endif /* !(GR_HAVE_NETINET_IN || GR_HAVE_ARPA_INET) */ - -static inline uint8_t ntohx(uint8_t x){ return x; } -static inline uint16_t ntohx(uint16_t x){ return ntohs(x); } -static inline uint32_t ntohx(uint32_t x){ return ntohl(x); } -static inline uint64_t ntohx(uint64_t x){ return ntohll(x);} -static inline uint8_t htonx(uint8_t x){ return x; } -static inline uint16_t htonx(uint16_t x){ return htons(x); } -static inline uint32_t htonx(uint32_t x){ return htonl(x); } -static inline uint64_t htonx(uint64_t x){ return htonll(x);} - -#endif /* INCLUDED_INET_H */ diff --git a/gruel/src/lib/pmt/pmt-serial-tags.scm b/gruel/src/lib/pmt/pmt-serial-tags.scm index ca25a43a8a..4f06bf75f8 100644 --- a/gruel/src/lib/pmt/pmt-serial-tags.scm +++ b/gruel/src/lib/pmt/pmt-serial-tags.scm @@ -33,6 +33,8 @@ (define pst-dict #x09) ; untagged-int32 n; followed by n key/value tuples (define pst-uniform-vector #x0a) +(define pst-uint64 #x0b) +(define pst-tuple #x0c) ;; u8, s8, u16, s16, u32, s32, u64, s64, f32, f64, c32, c64 ;; diff --git a/gruel/src/lib/pmt/pmt_serialize.cc b/gruel/src/lib/pmt/pmt_serialize.cc index de9644c3c6..a19809a667 100644 --- a/gruel/src/lib/pmt/pmt_serialize.cc +++ b/gruel/src/lib/pmt/pmt_serialize.cc @@ -79,7 +79,6 @@ serialize_untagged_f64(double i, std::streambuf &sb) } -#if 0 // always writes big-endian static bool serialize_untagged_u64(uint64_t i, std::streambuf &sb) @@ -93,7 +92,6 @@ serialize_untagged_u64(uint64_t i, std::streambuf &sb) sb.sputc((i >> 8) & 0xff); return sb.sputc((i >> 0) & 0xff) != std::streambuf::traits_type::eof(); } -#endif // ---------------------------------------------------------------- // input primitives @@ -152,7 +150,6 @@ deserialize_untagged_u32(uint32_t *ip, std::streambuf &sb) return t != std::streambuf::traits_type::eof(); } -#if 0 // always reads big-endian static bool deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb) @@ -181,7 +178,6 @@ deserialize_untagged_u64(uint64_t *ip, std::streambuf &sb) *ip = i; return t != std::streambuf::traits_type::eof(); } -#endif static bool deserialize_untagged_f64(double *ip, std::streambuf &sb) @@ -217,6 +213,24 @@ deserialize_untagged_f64(double *ip, std::streambuf &sb) return t != std::streambuf::traits_type::eof(); } +static bool +deserialize_tuple(pmt_t *tuple, std::streambuf &sb) +{ + uint32_t nitems; + bool ok = deserialize_untagged_u32(&nitems, sb); + pmt_t list(PMT_NIL); + for(uint32_t i=0; i<nitems; i++){ + pmt_t item = pmt_deserialize( sb ); + if(pmt_eq(list, PMT_NIL)){ + list = pmt_list1(item); + } else { + list = pmt_list_add(list, item); + } + } + (*tuple) = pmt_to_tuple(list); + return ok; +} + /* * Write portable byte-serial representation of \p obj to \p sb @@ -260,7 +274,13 @@ pmt_serialize(pmt_t obj, std::streambuf &sb) } if (pmt_is_number(obj)){ - + + if (pmt_is_uint64(obj)){ + uint64_t i = pmt_to_uint64(obj); + ok = serialize_untagged_u8(PST_UINT64, sb); + ok &= serialize_untagged_u64(i, sb); + return ok; + } else if (pmt_is_integer(obj)){ long i = pmt_to_long(obj); if (sizeof(long) > 4){ @@ -298,6 +318,16 @@ pmt_serialize(pmt_t obj, std::streambuf &sb) if (pmt_is_dict(obj)) throw pmt_notimplemented("pmt_serialize (dict)", obj); + if (pmt_is_tuple(obj)){ + size_t tuple_len = pmt::pmt_length(obj); + ok = serialize_untagged_u8(PST_TUPLE, sb); + ok &= serialize_untagged_u32(tuple_len, sb); + for(size_t i=0; i<tuple_len; i++){ + ok &= pmt_serialize(pmt_tuple_ref(obj, i), sb); + } + return ok; + } + //throw pmt_notimplemented("pmt_serialize (tuple)", obj); throw pmt_notimplemented("pmt_serialize (?)", obj); } @@ -315,7 +345,7 @@ pmt_deserialize(std::streambuf &sb) //uint8_t u8; uint16_t u16; uint32_t u32; - //uint32_t u64; + uint64_t u64; double f64; static char tmpbuf[1024]; @@ -347,6 +377,11 @@ pmt_deserialize(std::streambuf &sb) goto error; return pmt_from_long((int32_t) u32); + case PST_UINT64: + if(!deserialize_untagged_u64(&u64, sb)) + goto error; + return pmt_from_uint64(u64); + case PST_PAIR: return parse_pair(sb); @@ -362,6 +397,15 @@ pmt_deserialize(std::streambuf &sb) goto error; return pmt_make_rectangular( r,i ); } + + case PST_TUPLE: + { + pmt_t tuple; + if(!deserialize_tuple(&tuple, sb)){ + goto error; + } + return tuple; + } case PST_VECTOR: case PST_DICT: diff --git a/gruel/src/swig/CMakeLists.txt b/gruel/src/swig/CMakeLists.txt index f9d1758ec4..a0f84c8323 100644 --- a/gruel/src/swig/CMakeLists.txt +++ b/gruel/src/swig/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011-2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,7 +23,7 @@ include(GrPython) include(GrSwig) -set(GR_SWIG_INCLUDE_DIRS ${GRUEL_INCLUDE_DIRS}) +set(GR_SWIG_INCLUDE_DIRS ${GRUEL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) set(GR_SWIG_LIBRARIES gruel) set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/pmt_swig_doc.i) diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc index 0b44421085..6244abb357 100644 --- a/volk/apps/volk_profile.cc +++ b/volk/apps/volk_profile.cc @@ -33,6 +33,7 @@ int main(int argc, char *argv[]) { //VOLK_PROFILE(volk_16i_permute_and_scalar_add_a, 1e-4, 0, 2046, 10000, &results); //VOLK_PROFILE(volk_16i_x4_quad_max_star_16i_a, 1e-4, 0, 2046, 10000, &results); VOLK_PROFILE(volk_16u_byteswap_a, 0, 0, 204600, 10000, &results); + VOLK_PROFILE(volk_16i_32fc_dot_prod_32fc_a, 1e-4, 0, 204600, 10000, &results); VOLK_PROFILE(volk_32f_accumulator_s32f_a, 1e-4, 0, 204600, 10000, &results); VOLK_PROFILE(volk_32f_x2_add_32f_a, 1e-4, 0, 204600, 10000, &results); VOLK_PROFILE(volk_32f_x2_add_32f_u, 1e-4, 0, 204600, 10000, &results); @@ -49,6 +50,7 @@ int main(int argc, char *argv[]) { VOLK_PROFILE(volk_32fc_deinterleave_real_32f_a, 1e-4, 0, 204600, 5000, &results); VOLK_PROFILE(volk_32fc_deinterleave_real_64f_a, 1e-4, 0, 204600, 1000, &results); VOLK_PROFILE(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 204600, 10000, &results); + VOLK_PROFILE(volk_32fc_32f_dot_prod_32fc_a, 1e-4, 0, 204600, 10000, &results); VOLK_PROFILE(volk_32fc_index_max_16u_a, 3, 0, 204600, 10000, &results); VOLK_PROFILE(volk_32fc_s32f_magnitude_16i_a, 1, 32768, 204600, 100, &results); VOLK_PROFILE(volk_32fc_magnitude_32f_a, 1e-4, 0, 204600, 1000, &results); @@ -76,6 +78,7 @@ int main(int argc, char *argv[]) { VOLK_PROFILE(volk_32f_x2_divide_32f_a, 1e-4, 0, 204600, 2000, &results); VOLK_PROFILE(volk_32f_x2_dot_prod_32f_a, 1e-4, 0, 204600, 5000, &results); VOLK_PROFILE(volk_32f_x2_dot_prod_32f_u, 1e-4, 0, 204600, 5000, &results); + VOLK_PROFILE(volk_32f_x2_dot_prod_16i_a, 1e-4, 0, 204600, 5000, &results); //VOLK_PROFILE(volk_32f_s32f_32f_fm_detect_32f_a, 1e-4, 2046, 10000, &results); VOLK_PROFILE(volk_32f_index_max_16u_a, 3, 0, 204600, 5000, &results); VOLK_PROFILE(volk_32f_x2_s32f_interleave_16ic_a, 1, 32768, 204600, 3000, &results); diff --git a/volk/gen/archs.xml b/volk/gen/archs.xml index 2c9ab41a55..a18455801d 100644 --- a/volk/gen/archs.xml +++ b/volk/gen/archs.xml @@ -2,6 +2,7 @@ <grammar> <arch name="generic"> <!-- name is required--> + <alignment>1</alignment> </arch> <arch name="altivec"> diff --git a/volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h b/volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h new file mode 100644 index 0000000000..940aa5de7c --- /dev/null +++ b/volk/include/volk/volk_16i_32fc_dot_prod_32fc_a.h @@ -0,0 +1,122 @@ +#ifndef INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H +#define INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H + +#include <volk/volk_common.h> +#include<stdio.h> + + +#ifdef LV_HAVE_GENERIC + + +static inline void volk_16i_32fc_dot_prod_32fc_a_generic(lv_32fc_t* result, const short* input, const lv_32fc_t * taps, unsigned int num_points) { + + static const int N_UNROLL = 4; + + lv_32fc_t acc0 = 0; + lv_32fc_t acc1 = 0; + lv_32fc_t acc2 = 0; + lv_32fc_t acc3 = 0; + + unsigned i = 0; + unsigned n = (num_points / N_UNROLL) * N_UNROLL; + + for(i = 0; i < n; i += N_UNROLL) { + acc0 += taps[i + 0] * (float)input[i + 0]; + acc1 += taps[i + 1] * (float)input[i + 1]; + acc2 += taps[i + 2] * (float)input[i + 2]; + acc3 += taps[i + 3] * (float)input[i + 3]; + } + + for(; i < num_points; i++) { + acc0 += taps[i] * (float)input[i]; + } + + *result = acc0 + acc1 + acc2 + acc3; +} + +#endif /*LV_HAVE_GENERIC*/ + + +#ifdef LV_HAVE_SSE + + +static inline void volk_16i_32fc_dot_prod_32fc_a_sse( lv_32fc_t* result, const short* input, const lv_32fc_t* taps, unsigned int num_points) { + + unsigned int number = 0; + const unsigned int sixteenthPoints = num_points / 8; + + float res[2]; + float *realpt = &res[0], *imagpt = &res[1]; + const short* aPtr = input; + const float* bPtr = (float*)taps; + + __m64 m0, m1; + __m128 f0, f1, f2, f3; + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 c0Val, c1Val, c2Val, c3Val; + + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); + + for(;number < sixteenthPoints; number++){ + + m0 = _mm_set_pi16(*(aPtr+3), *(aPtr+2), *(aPtr+1), *(aPtr+0)); + m1 = _mm_set_pi16(*(aPtr+7), *(aPtr+6), *(aPtr+5), *(aPtr+4)); + f0 = _mm_cvtpi16_ps(m0); + f1 = _mm_cvtpi16_ps(m0); + f2 = _mm_cvtpi16_ps(m1); + f3 = _mm_cvtpi16_ps(m1); + + a0Val = _mm_unpacklo_ps(f0, f1); + a1Val = _mm_unpackhi_ps(f0, f1); + a2Val = _mm_unpacklo_ps(f2, f3); + a3Val = _mm_unpackhi_ps(f2, f3); + + b0Val = _mm_load_ps(bPtr); + b1Val = _mm_load_ps(bPtr+4); + b2Val = _mm_load_ps(bPtr+8); + b3Val = _mm_load_ps(bPtr+12); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1); + dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2); + dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3); + + aPtr += 8; + bPtr += 16; + } + + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); + + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; + + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector + + *realpt = dotProductVector[0]; + *imagpt = dotProductVector[1]; + *realpt += dotProductVector[2]; + *imagpt += dotProductVector[3]; + + number = sixteenthPoints*8; + for(;number < num_points; number++){ + *realpt += ((*aPtr) * (*bPtr++)); + *imagpt += ((*aPtr++) * (*bPtr++)); + } + + *result = *(lv_32fc_t*)(&res[0]); +} + +#endif /*LV_HAVE_SSE*/ + + +#endif /*INCLUDED_volk_16i_32fc_dot_prod_32fc_a_H*/ diff --git a/volk/include/volk/volk_32f_x2_dot_prod_16i_a.h b/volk/include/volk/volk_32f_x2_dot_prod_16i_a.h new file mode 100644 index 0000000000..961c2418ca --- /dev/null +++ b/volk/include/volk/volk_32f_x2_dot_prod_16i_a.h @@ -0,0 +1,98 @@ +#ifndef INCLUDED_volk_32f_x2_dot_prod_16i_a_H +#define INCLUDED_volk_32f_x2_dot_prod_16i_a_H + +#include <volk/volk_common.h> +#include<stdio.h> + + +#ifdef LV_HAVE_GENERIC + + +static inline void volk_32f_x2_dot_prod_16i_a_generic(int16_t* result, const float* input, const float* taps, unsigned int num_points) { + + float dotProduct = 0; + const float* aPtr = input; + const float* bPtr= taps; + unsigned int number = 0; + + for(number = 0; number < num_points; number++){ + dotProduct += ((*aPtr++) * (*bPtr++)); + } + + *result = (int16_t)dotProduct; +} + +#endif /*LV_HAVE_GENERIC*/ + + +#ifdef LV_HAVE_SSE + + +static inline void volk_32f_x2_dot_prod_16i_a_sse(int16_t* result, const float* input, const float* taps, unsigned int num_points) { + + unsigned int number = 0; + const unsigned int sixteenthPoints = num_points / 16; + + float dotProduct = 0; + const float* aPtr = input; + const float* bPtr = taps; + + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 c0Val, c1Val, c2Val, c3Val; + + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); + + for(;number < sixteenthPoints; number++){ + + a0Val = _mm_load_ps(aPtr); + a1Val = _mm_load_ps(aPtr+4); + a2Val = _mm_load_ps(aPtr+8); + a3Val = _mm_load_ps(aPtr+12); + b0Val = _mm_load_ps(bPtr); + b1Val = _mm_load_ps(bPtr+4); + b2Val = _mm_load_ps(bPtr+8); + b3Val = _mm_load_ps(bPtr+12); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1); + dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2); + dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3); + + aPtr += 16; + bPtr += 16; + } + + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); + + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; + + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector + + dotProduct = dotProductVector[0]; + dotProduct += dotProductVector[1]; + dotProduct += dotProductVector[2]; + dotProduct += dotProductVector[3]; + + number = sixteenthPoints*16; + for(;number < num_points; number++){ + dotProduct += ((*aPtr++) * (*bPtr++)); + } + + *result = (short)dotProduct; + +} + +#endif /*LV_HAVE_SSE*/ + +#endif /*INCLUDED_volk_32f_x2_dot_prod_16i_a_H*/ diff --git a/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h b/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h index 448b2fdc01..067c33ad89 100644 --- a/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h +++ b/volk/include/volk/volk_32f_x2_dot_prod_32f_a.h @@ -31,39 +31,60 @@ static inline void volk_32f_x2_dot_prod_32f_a_generic(float * result, const floa static inline void volk_32f_x2_dot_prod_32f_a_sse( float* result, const float* input, const float* taps, unsigned int num_points) { unsigned int number = 0; - const unsigned int quarterPoints = num_points / 4; + const unsigned int sixteenthPoints = num_points / 16; float dotProduct = 0; const float* aPtr = input; const float* bPtr = taps; - __m128 aVal, bVal, cVal; - - __m128 dotProdVal = _mm_setzero_ps(); - - for(;number < quarterPoints; number++){ + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 c0Val, c1Val, c2Val, c3Val; - aVal = _mm_load_ps(aPtr); - bVal = _mm_load_ps(bPtr); + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); - cVal = _mm_mul_ps(aVal, bVal); - - dotProdVal = _mm_add_ps(cVal, dotProdVal); + for(;number < sixteenthPoints; number++){ - aPtr += 4; - bPtr += 4; + a0Val = _mm_load_ps(aPtr); + a1Val = _mm_load_ps(aPtr+4); + a2Val = _mm_load_ps(aPtr+8); + a3Val = _mm_load_ps(aPtr+12); + b0Val = _mm_load_ps(bPtr); + b1Val = _mm_load_ps(bPtr+4); + b2Val = _mm_load_ps(bPtr+8); + b3Val = _mm_load_ps(bPtr+12); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1); + dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2); + dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3); + + aPtr += 16; + bPtr += 16; } + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; - _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector dotProduct = dotProductVector[0]; dotProduct += dotProductVector[1]; dotProduct += dotProductVector[2]; dotProduct += dotProductVector[3]; - number = quarterPoints * 4; + number = sixteenthPoints*16; for(;number < num_points; number++){ dotProduct += ((*aPtr++) * (*bPtr++)); } @@ -80,38 +101,59 @@ static inline void volk_32f_x2_dot_prod_32f_a_sse( float* result, const float* static inline void volk_32f_x2_dot_prod_32f_a_sse3(float * result, const float * input, const float * taps, unsigned int num_points) { unsigned int number = 0; - const unsigned int quarterPoints = num_points / 4; + const unsigned int sixteenthPoints = num_points / 16; float dotProduct = 0; const float* aPtr = input; const float* bPtr = taps; - __m128 aVal, bVal, cVal; - - __m128 dotProdVal = _mm_setzero_ps(); - - for(;number < quarterPoints; number++){ + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 c0Val, c1Val, c2Val, c3Val; - aVal = _mm_load_ps(aPtr); - bVal = _mm_load_ps(bPtr); + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); - cVal = _mm_mul_ps(aVal, bVal); - - dotProdVal = _mm_hadd_ps(dotProdVal, cVal); + for(;number < sixteenthPoints; number++){ - aPtr += 4; - bPtr += 4; + a0Val = _mm_load_ps(aPtr); + a1Val = _mm_load_ps(aPtr+4); + a2Val = _mm_load_ps(aPtr+8); + a3Val = _mm_load_ps(aPtr+12); + b0Val = _mm_load_ps(bPtr); + b1Val = _mm_load_ps(bPtr+4); + b2Val = _mm_load_ps(bPtr+8); + b3Val = _mm_load_ps(bPtr+12); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(dotProdVal0, c0Val); + dotProdVal1 = _mm_add_ps(dotProdVal1, c1Val); + dotProdVal2 = _mm_add_ps(dotProdVal2, c2Val); + dotProdVal3 = _mm_add_ps(dotProdVal3, c3Val); + + aPtr += 16; + bPtr += 16; } - __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; - dotProdVal = _mm_hadd_ps(dotProdVal, dotProdVal); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); - _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector dotProduct = dotProductVector[0]; dotProduct += dotProductVector[1]; + dotProduct += dotProductVector[2]; + dotProduct += dotProductVector[3]; - number = quarterPoints * 4; + number = sixteenthPoints*16; for(;number < num_points; number++){ dotProduct += ((*aPtr++) * (*bPtr++)); } @@ -182,4 +224,67 @@ static inline void volk_32f_x2_dot_prod_32f_a_sse4_1(float * result, const float #endif /*LV_HAVE_SSE4_1*/ +#ifdef LV_HAVE_AVX + +#include <immintrin.h> + +static inline void volk_32f_x2_dot_prod_32f_a_avx( float* result, const float* input, const float* taps, unsigned int num_points) { + + unsigned int number = 0; + const unsigned int sixteenthPoints = num_points / 16; + + float dotProduct = 0; + const float* aPtr = input; + const float* bPtr = taps; + + __m256 a0Val, a1Val; + __m256 b0Val, b1Val; + __m256 c0Val, c1Val; + + __m256 dotProdVal0 = _mm256_setzero_ps(); + __m256 dotProdVal1 = _mm256_setzero_ps(); + + for(;number < sixteenthPoints; number++){ + + a0Val = _mm256_load_ps(aPtr); + a1Val = _mm256_load_ps(aPtr+8); + b0Val = _mm256_load_ps(bPtr); + b1Val = _mm256_load_ps(bPtr+8); + + c0Val = _mm256_mul_ps(a0Val, b0Val); + c1Val = _mm256_mul_ps(a1Val, b1Val); + + dotProdVal0 = _mm256_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm256_add_ps(c1Val, dotProdVal1); + + aPtr += 16; + bPtr += 16; + } + + dotProdVal0 = _mm256_add_ps(dotProdVal0, dotProdVal1); + + __VOLK_ATTR_ALIGNED(32) float dotProductVector[8]; + + _mm256_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector + + dotProduct = dotProductVector[0]; + dotProduct += dotProductVector[1]; + dotProduct += dotProductVector[2]; + dotProduct += dotProductVector[3]; + dotProduct += dotProductVector[4]; + dotProduct += dotProductVector[5]; + dotProduct += dotProductVector[6]; + dotProduct += dotProductVector[7]; + + number = sixteenthPoints*16; + for(;number < num_points; number++){ + dotProduct += ((*aPtr++) * (*bPtr++)); + } + + *result = dotProduct; + +} + +#endif /*LV_HAVE_AVX*/ + #endif /*INCLUDED_volk_32f_x2_dot_prod_32f_a_H*/ diff --git a/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h b/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h index 3b7284b575..ab33a25876 100644 --- a/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h +++ b/volk/include/volk/volk_32f_x2_dot_prod_32f_u.h @@ -1,6 +1,7 @@ #ifndef INCLUDED_volk_32f_x2_dot_prod_32f_u_H #define INCLUDED_volk_32f_x2_dot_prod_32f_u_H +#include <volk/volk_common.h> #include<stdio.h> @@ -30,41 +31,65 @@ static inline void volk_32f_x2_dot_prod_32f_u_generic(float * result, const floa static inline void volk_32f_x2_dot_prod_32f_u_sse( float* result, const float* input, const float* taps, unsigned int num_points) { unsigned int number = 0; - const unsigned int quarterPoints = num_points / 4; + const unsigned int sixteenthPoints = num_points / 16; float dotProduct = 0; const float* aPtr = input; const float* bPtr = taps; - __m128 aVal, bVal, cVal; - - __m128 dotProdVal = _mm_setzero_ps(); - - for(;number < quarterPoints; number++){ + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 c0Val, c1Val, c2Val, c3Val; - aVal = _mm_loadu_ps(aPtr); - bVal = _mm_loadu_ps(bPtr); + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); - cVal = _mm_mul_ps(aVal, bVal); - - dotProdVal = _mm_add_ps(cVal, dotProdVal); + for(;number < sixteenthPoints; number++){ - aPtr += 4; - bPtr += 4; + a0Val = _mm_load_ps(aPtr); + a1Val = _mm_load_ps(aPtr+4); + a2Val = _mm_load_ps(aPtr+8); + a3Val = _mm_load_ps(aPtr+12); + b0Val = _mm_load_ps(bPtr); + b1Val = _mm_load_ps(bPtr+4); + b2Val = _mm_load_ps(bPtr+8); + b3Val = _mm_load_ps(bPtr+12); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1); + dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2); + dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3); + + aPtr += 16; + bPtr += 16; } + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; - _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector dotProduct = dotProductVector[0]; dotProduct += dotProductVector[1]; dotProduct += dotProductVector[2]; dotProduct += dotProductVector[3]; - number = quarterPoints * 4; + number = sixteenthPoints*16; for(;number < num_points; number++){ dotProduct += ((*aPtr++) * (*bPtr++)); + dotProduct += ((*aPtr++) * (*bPtr++)); + dotProduct += ((*aPtr++) * (*bPtr++)); + dotProduct += ((*aPtr++) * (*bPtr++)); } *result = dotProduct; @@ -79,38 +104,59 @@ static inline void volk_32f_x2_dot_prod_32f_u_sse( float* result, const float* static inline void volk_32f_x2_dot_prod_32f_u_sse3(float * result, const float * input, const float * taps, unsigned int num_points) { unsigned int number = 0; - const unsigned int quarterPoints = num_points / 4; + const unsigned int sixteenthPoints = num_points / 16; float dotProduct = 0; const float* aPtr = input; const float* bPtr = taps; - __m128 aVal, bVal, cVal; - - __m128 dotProdVal = _mm_setzero_ps(); - - for(;number < quarterPoints; number++){ + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 c0Val, c1Val, c2Val, c3Val; - aVal = _mm_loadu_ps(aPtr); - bVal = _mm_loadu_ps(bPtr); + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); - cVal = _mm_mul_ps(aVal, bVal); - - dotProdVal = _mm_hadd_ps(dotProdVal, cVal); + for(;number < sixteenthPoints; number++){ - aPtr += 4; - bPtr += 4; + a0Val = _mm_load_ps(aPtr); + a1Val = _mm_load_ps(aPtr+4); + a2Val = _mm_load_ps(aPtr+8); + a3Val = _mm_load_ps(aPtr+12); + b0Val = _mm_load_ps(bPtr); + b1Val = _mm_load_ps(bPtr+4); + b2Val = _mm_load_ps(bPtr+8); + b3Val = _mm_load_ps(bPtr+12); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(dotProdVal0, c0Val); + dotProdVal1 = _mm_add_ps(dotProdVal1, c1Val); + dotProdVal2 = _mm_add_ps(dotProdVal2, c2Val); + dotProdVal3 = _mm_add_ps(dotProdVal3, c3Val); + + aPtr += 16; + bPtr += 16; } - __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; - dotProdVal = _mm_hadd_ps(dotProdVal, dotProdVal); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); - _mm_store_ps(dotProductVector,dotProdVal); // Store the results back into the dot product vector + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector dotProduct = dotProductVector[0]; dotProduct += dotProductVector[1]; + dotProduct += dotProductVector[2]; + dotProduct += dotProductVector[3]; - number = quarterPoints * 4; + number = sixteenthPoints*16; for(;number < num_points; number++){ dotProduct += ((*aPtr++) * (*bPtr++)); } @@ -141,15 +187,15 @@ static inline void volk_32f_x2_dot_prod_32f_u_sse4_1(float * result, const float for(;number < sixteenthPoints; number++){ - aVal1 = _mm_loadu_ps(aPtr); aPtr += 4; - aVal2 = _mm_loadu_ps(aPtr); aPtr += 4; - aVal3 = _mm_loadu_ps(aPtr); aPtr += 4; - aVal4 = _mm_loadu_ps(aPtr); aPtr += 4; + aVal1 = _mm_load_ps(aPtr); aPtr += 4; + aVal2 = _mm_load_ps(aPtr); aPtr += 4; + aVal3 = _mm_load_ps(aPtr); aPtr += 4; + aVal4 = _mm_load_ps(aPtr); aPtr += 4; - bVal1 = _mm_loadu_ps(bPtr); bPtr += 4; - bVal2 = _mm_loadu_ps(bPtr); bPtr += 4; - bVal3 = _mm_loadu_ps(bPtr); bPtr += 4; - bVal4 = _mm_loadu_ps(bPtr); bPtr += 4; + bVal1 = _mm_load_ps(bPtr); bPtr += 4; + bVal2 = _mm_load_ps(bPtr); bPtr += 4; + bVal3 = _mm_load_ps(bPtr); bPtr += 4; + bVal4 = _mm_load_ps(bPtr); bPtr += 4; cVal1 = _mm_dp_ps(aVal1, bVal1, 0xF1); cVal2 = _mm_dp_ps(aVal2, bVal2, 0xF2); @@ -181,4 +227,67 @@ static inline void volk_32f_x2_dot_prod_32f_u_sse4_1(float * result, const float #endif /*LV_HAVE_SSE4_1*/ +#ifdef LV_HAVE_AVX + +#include <immintrin.h> + +static inline void volk_32f_x2_dot_prod_32f_u_avx( float* result, const float* input, const float* taps, unsigned int num_points) { + + unsigned int number = 0; + const unsigned int sixteenthPoints = num_points / 16; + + float dotProduct = 0; + const float* aPtr = input; + const float* bPtr = taps; + + __m256 a0Val, a1Val; + __m256 b0Val, b1Val; + __m256 c0Val, c1Val; + + __m256 dotProdVal0 = _mm256_setzero_ps(); + __m256 dotProdVal1 = _mm256_setzero_ps(); + + for(;number < sixteenthPoints; number++){ + + a0Val = _mm256_loadu_ps(aPtr); + a1Val = _mm256_loadu_ps(aPtr+8); + b0Val = _mm256_loadu_ps(bPtr); + b1Val = _mm256_loadu_ps(bPtr+8); + + c0Val = _mm256_mul_ps(a0Val, b0Val); + c1Val = _mm256_mul_ps(a1Val, b1Val); + + dotProdVal0 = _mm256_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm256_add_ps(c1Val, dotProdVal1); + + aPtr += 16; + bPtr += 16; + } + + dotProdVal0 = _mm256_add_ps(dotProdVal0, dotProdVal1); + + __VOLK_ATTR_ALIGNED(32) float dotProductVector[8]; + + _mm256_storeu_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector + + dotProduct = dotProductVector[0]; + dotProduct += dotProductVector[1]; + dotProduct += dotProductVector[2]; + dotProduct += dotProductVector[3]; + dotProduct += dotProductVector[4]; + dotProduct += dotProductVector[5]; + dotProduct += dotProductVector[6]; + dotProduct += dotProductVector[7]; + + number = sixteenthPoints*16; + for(;number < num_points; number++){ + dotProduct += ((*aPtr++) * (*bPtr++)); + } + + *result = dotProduct; + +} + +#endif /*LV_HAVE_AVX*/ + #endif /*INCLUDED_volk_32f_x2_dot_prod_32f_u_H*/ diff --git a/volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h b/volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h new file mode 100644 index 0000000000..109b787e8c --- /dev/null +++ b/volk/include/volk/volk_32fc_32f_dot_prod_32fc_a.h @@ -0,0 +1,111 @@ +#ifndef INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H +#define INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H + +#include <volk/volk_common.h> +#include<stdio.h> + + +#ifdef LV_HAVE_GENERIC + + +static inline void volk_32fc_32f_dot_prod_32fc_a_generic(lv_32fc_t* result, const lv_32fc_t* input, const float * taps, unsigned int num_points) { + + float res[2]; + float *realpt = &res[0], *imagpt = &res[1]; + const float* aPtr = (float*)input; + const float* bPtr= taps; + unsigned int number = 0; + + *realpt = 0; + *imagpt = 0; + + for(number = 0; number < num_points; number++){ + *realpt += ((*aPtr++) * (*bPtr)); + *imagpt += ((*aPtr++) * (*bPtr++)); + } + + *result = *(lv_32fc_t*)(&res[0]); +} + +#endif /*LV_HAVE_GENERIC*/ + + +#ifdef LV_HAVE_SSE + + +static inline void volk_32fc_32f_dot_prod_32fc_a_sse( lv_32fc_t* result, const lv_32fc_t* input, const float* taps, unsigned int num_points) { + + unsigned int number = 0; + const unsigned int sixteenthPoints = num_points / 8; + + float res[2]; + float *realpt = &res[0], *imagpt = &res[1]; + const float* aPtr = (float*)input; + const float* bPtr = taps; + + __m128 a0Val, a1Val, a2Val, a3Val; + __m128 b0Val, b1Val, b2Val, b3Val; + __m128 x0Val, x1Val, x2Val, x3Val; + __m128 c0Val, c1Val, c2Val, c3Val; + + __m128 dotProdVal0 = _mm_setzero_ps(); + __m128 dotProdVal1 = _mm_setzero_ps(); + __m128 dotProdVal2 = _mm_setzero_ps(); + __m128 dotProdVal3 = _mm_setzero_ps(); + + for(;number < sixteenthPoints; number++){ + + a0Val = _mm_load_ps(aPtr); + a1Val = _mm_load_ps(aPtr+4); + a2Val = _mm_load_ps(aPtr+8); + a3Val = _mm_load_ps(aPtr+12); + + x0Val = _mm_load_ps(bPtr); + x1Val = _mm_load_ps(bPtr); + x2Val = _mm_load_ps(bPtr+4); + x3Val = _mm_load_ps(bPtr+4); + b0Val = _mm_unpacklo_ps(x0Val, x1Val); + b1Val = _mm_unpackhi_ps(x0Val, x1Val); + b2Val = _mm_unpacklo_ps(x2Val, x3Val); + b3Val = _mm_unpackhi_ps(x2Val, x3Val); + + c0Val = _mm_mul_ps(a0Val, b0Val); + c1Val = _mm_mul_ps(a1Val, b1Val); + c2Val = _mm_mul_ps(a2Val, b2Val); + c3Val = _mm_mul_ps(a3Val, b3Val); + + dotProdVal0 = _mm_add_ps(c0Val, dotProdVal0); + dotProdVal1 = _mm_add_ps(c1Val, dotProdVal1); + dotProdVal2 = _mm_add_ps(c2Val, dotProdVal2); + dotProdVal3 = _mm_add_ps(c3Val, dotProdVal3); + + aPtr += 16; + bPtr += 8; + } + + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal1); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal2); + dotProdVal0 = _mm_add_ps(dotProdVal0, dotProdVal3); + + __VOLK_ATTR_ALIGNED(16) float dotProductVector[4]; + + _mm_store_ps(dotProductVector,dotProdVal0); // Store the results back into the dot product vector + + *realpt = dotProductVector[0]; + *imagpt = dotProductVector[1]; + *realpt += dotProductVector[2]; + *imagpt += dotProductVector[3]; + + number = sixteenthPoints*8; + for(;number < num_points; number++){ + *realpt += ((*aPtr++) * (*bPtr)); + *imagpt += ((*aPtr++) * (*bPtr++)); + } + + *result = *(lv_32fc_t*)(&res[0]); +} + +#endif /*LV_HAVE_SSE*/ + + +#endif /*INCLUDED_volk_32fc_32f_dot_prod_32fc_a_H*/ diff --git a/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h b/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h index 80c55e75f3..05732b1eab 100644 --- a/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h +++ b/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h @@ -174,12 +174,10 @@ static inline void volk_32fc_s32fc_x2_rotator_32fc_a_avx(lv_32fc_t* outVector, c printf("%f, %f\n", lv_creal(phase_Ptr[2]), lv_cimag(phase_Ptr[2])); printf("%f, %f\n", lv_creal(phase_Ptr[3]), lv_cimag(phase_Ptr[3])); printf("incr: %f, %f\n", lv_creal(incr), lv_cimag(incr));*/ - __m256 aVal, phase_Val, inc_Val, yl, yh, tmp1, tmp2, z, ylp, yhp, tmp1p, tmp2p, negated, zeros; + __m256 aVal, phase_Val, inc_Val, yl, yh, tmp1, tmp2, z, ylp, yhp, tmp1p, tmp2p; phase_Val = _mm256_loadu_ps((float*)phase_Ptr); inc_Val = _mm256_set_ps(lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr)); - zeros = _mm256_set1_ps(0.0); - negated = _mm256_set1_ps(-1.0); const unsigned int fourthPoints = num_points / 4; diff --git a/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h b/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h index cb2ac4c67e..166a883a7f 100644 --- a/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h +++ b/volk/include/volk/volk_32fc_x2_dot_prod_32fc_a.h @@ -18,40 +18,26 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_generic(lv_32fc_t* result, const unsigned int n_2_ccomplex_blocks = num_bytes >> 4; unsigned int isodd = (num_bytes >> 3) &1; - - float sum0[2] = {0,0}; float sum1[2] = {0,0}; unsigned int i = 0; - for(i = 0; i < n_2_ccomplex_blocks; ++i) { - - sum0[0] += in[0] * tp[0] - in[1] * tp[1]; sum0[1] += in[0] * tp[1] + in[1] * tp[0]; sum1[0] += in[2] * tp[2] - in[3] * tp[3]; sum1[1] += in[2] * tp[3] + in[3] * tp[2]; - in += 4; tp += 4; - } - res[0] = sum0[0] + sum1[0]; res[1] = sum0[1] + sum1[1]; - - for(i = 0; i < isodd; ++i) { - - *result += input[(num_bytes >> 3) - 1] * taps[(num_bytes >> 3) - 1]; - } - } #endif /*LV_HAVE_GENERIC*/ @@ -177,14 +163,8 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse_64(lv_32fc_t* result, const ); - int getem = num_bytes % 16; - - - for(; getem > 0; getem -= 8) { - - + if(((num_bytes >> 3) & 1)) { *result += (input[(num_bytes >> 3) - 1] * taps[(num_bytes >> 3) - 1]); - } return; @@ -363,7 +343,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse3(lv_32fc_t* result, const lv dotProduct += ( dotProductVector[0] + dotProductVector[1] ); - if((num_bytes >> 2) != 0) { + if(((num_bytes >> 3) & 1) != 0) { dotProduct += (*a) * (*b); } @@ -377,9 +357,7 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse3(lv_32fc_t* result, const lv #include <smmintrin.h> static inline void volk_32fc_x2_dot_prod_32fc_a_sse4_1(lv_32fc_t* result, const lv_32fc_t* input, const lv_32fc_t* taps, unsigned int num_bytes) { - volk_32fc_x2_dot_prod_32fc_a_sse3(result, input, taps, num_bytes); - // SSE3 version runs twice as fast as the SSE4.1 version, so turning off SSE4 version for now - /* + __m128 xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, real0, real1, im0, im1; float *p_input, *p_taps; __m64 *p_result; @@ -442,12 +420,8 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse4_1(lv_32fc_t* result, const } - - - real1 = _mm_xor_ps(real1, (__m128)neg); - im0 = _mm_add_ps(im0, im1); real0 = _mm_add_ps(real0, real1); @@ -459,7 +433,6 @@ static inline void volk_32fc_x2_dot_prod_32fc_a_sse4_1(lv_32fc_t* result, const *result += input[i] * taps[i]; } - */ } #endif /*LV_HAVE_SSE4_1*/ diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc index aac6767298..d1eb1cacbb 100644 --- a/volk/lib/testqa.cc +++ b/volk/lib/testqa.cc @@ -20,6 +20,7 @@ VOLK_RUN_TESTS(volk_16i_convert_8i_u, 0, 0, 20460, 1); //VOLK_RUN_TESTS(volk_16i_permute_and_scalar_add_a, 1e-4, 0, 2046, 1000); //VOLK_RUN_TESTS(volk_16i_x4_quad_max_star_16i_a, 1e-4, 0, 2046, 1000); VOLK_RUN_TESTS(volk_16u_byteswap_a, 0, 0, 20460, 1); +//VOLK_RUN_TESTS(volk_16i_32fc_dot_prod_32fc_a, 1e-4, 0, 204600, 1); VOLK_RUN_TESTS(volk_32f_accumulator_s32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_add_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_add_32f_u, 1e-4, 0, 20460, 1); @@ -34,7 +35,8 @@ VOLK_RUN_TESTS(volk_32fc_deinterleave_64f_x2_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_s32f_deinterleave_real_16i_a, 0, 32768, 20460, 1); VOLK_RUN_TESTS(volk_32fc_deinterleave_real_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_deinterleave_real_64f_a, 1e-4, 0, 20460, 1); -VOLK_RUN_TESTS(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 204600, 1); +VOLK_RUN_TESTS(volk_32fc_x2_dot_prod_32fc_a, 1e-4, 0, 2046000, 1); +VOLK_RUN_TESTS(volk_32fc_32f_dot_prod_32fc_a, 1e-4, 0, 2046000, 1); VOLK_RUN_TESTS(volk_32fc_index_max_16u_a, 3, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_s32f_magnitude_16i_a, 1, 32768, 20460, 1); VOLK_RUN_TESTS(volk_32fc_magnitude_32f_a, 1e-4, 0, 20460, 1); @@ -52,7 +54,8 @@ VOLK_RUN_TESTS(volk_32fc_x2_square_dist_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_x2_s32f_square_dist_scalar_mult_32f_a, 1e-4, 10, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_divide_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_a, 1e-4, 0, 204600, 1); -VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_u, 1e-4, 0, 204600, 1); +//VOLK_RUN_TESTS(volk_32f_x2_dot_prod_32f_u, 1e-4, 0, 204600, 1); +VOLK_RUN_TESTS(volk_32f_x2_dot_prod_16i_a, 1e-4, 0, 204600, 1); //VOLK_RUN_TESTS(volk_32f_s32f_32f_fm_detect_32f_a, 1e-4, 2046, 10000); VOLK_RUN_TESTS(volk_32f_index_max_16u_a, 3, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_s32f_interleave_16ic_a, 1, 32767, 20460, 1); |