diff options
291 files changed, 16513 insertions, 2264 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 73473c5f3..dad398e8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,8 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) # Set the version information here set(VERSION_INFO_MAJOR_VERSION 3) set(VERSION_INFO_API_COMPAT 6) -set(VERSION_INFO_MINOR_VERSION 0) -set(VERSION_INFO_MAINT_VERSION 0) +set(VERSION_INFO_MINOR_VERSION 1) +set(VERSION_INFO_MAINT_VERSION git) include(GrVersion) #setup version info # Append -O2 optimization flag for Debug builds @@ -228,6 +228,7 @@ add_subdirectory(gruel) add_subdirectory(gnuradio-core) add_subdirectory(grc) +add_subdirectory(gr-fft) add_subdirectory(gr-atsc) add_subdirectory(gr-audio) add_subdirectory(gr-comedi) @@ -46,21 +46,16 @@ http://gnuradio.org/redmine/projects/gnuradio/wiki/DevelopingWithGit How to Build GNU Radio: - (1) Ensure that you've satisfied the external dependencies listed - below. The word "system" is used to mean "operating system - and/or distribution", and means a full operating system, - including kernel, user-space utilties, and a packaging system - for additional software. On Linux, this means what - "distribution" means. - - The following GNU/Linux distributions are known to come with all - required dependencies pre-packaged: Ubuntu >8.10, SuSE 10.0 (the - pay version, not the free download), Fedora Core >9. Other - distribution may work too. We know these three are easy. The - required packages may be contained on your installation CD/DVD, - or may be loaded over the net. The specifics vary depending on - your GNU/Linux distribution. +For more complete instructions, see the "Building GNU Radio" page in +the GNU Radio manual (can be built or found online at +http://gnuradio.org/doc/doxygen/page_build.html). +See these steps fow a quick build guide. + + (1) Ensure that you've satisfied the external dependencies. These + dependencies are listed in the manual's build page and are not + presented here to reduce duplication errors. + On systems using pkgsrc (e.g. NetBSD and Dragonfly), build meta-packages/gnuradio, which will build a previous release and force installation of the dependencies. Then pkg_delete the @@ -105,147 +100,20 @@ with '-O3', which is the default. ------------------------------------------------------------------------------- - External dependencies + NOTES ------------------------------------------------------------------------------- -Prerequisites: Before trying to build these from source, please try -your system's installation tool (apt-get, pkg_install, YaST, yum, -urpmi, etc.) first. Most recent systems have these packages -available. - -You'll need to do a bit of sleuthing to figure out what your OS and -packaging system calls these. If your system uses the convention of -splitting files needed to run programs compiled with foo and files -needed to do the compilation into packages named foo and foo-devel, -install both packages. (Most GNU/Linux systems are like this, but -pkgsrc is not and instead uses -devel to indicate a package of a -not-yet-released or unstable version.) - -For those using pkgsrc, see gnuradio-pkg_chk.conf. Those not using -pkgsrc may also find the list useful. - -(0) GNU make - -It used to be required to have a "reasonable make", meaning GNU make, -BSD make, or perhaps Solaris make. It is now required to use GNU -make. Version 3.81 should certainly work; the intent is not to -require the bleeding edge. - -Note that the examples below are written with "make". They probably -should say "gmake", as GNU make is installed as gmake when it is not -the native make. - -(1) cmake 2.6 or later http://www.cmake.org/cmake/resources/software.html - -(2) pkgconfig 0.15.0 or later http://www.freedesktop.org/Software/pkgconfig - -From the web site: - -pkgconfig is a system for managing library compile/link flags that -works with automake and autoconf. It replaces the ubiquitous *-config -scripts you may have seen with a single tool. - - -(3) FFTW 3.0 or later http://www.fftw.org - -IMPORTANT!!! When building FFTW, you MUST use the --enable-single and ---enable-shared configure options. This builds the single precision -floating point version which we use. You should also use either the ---enable-3dnow or --enable-sse options if you're on an Athlon or Pentium -respectively. - -GNU/Linux packages of single-precision fftw are typically called -fftw3f. - -In systems using pkgsrc, install math/fftwf, which provides the -single-precision libraries. - - -(4) Python 2.5 or later http://www.python.org - -Python 2.5 or later is now required. If your system splits -python into a bunch of separate packages including python-devel or -libpython you'll most likely need those too. - - -(5) Numpy python library http://numeric.scipy.org - -Provides a high performance array type for Python. -http://numpy.scipy.org -http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=175103 - - -(6) The Boost C++ Libraries (1.35 or later) http://www.boost.org - -We use Smart Pointers, the thread library and a bunch of other boost stuff. -If your system doesn't have boost 1.35 or later, see README.building-boost -for additional info. (Note: Mac OSX systems require 1.37 or later.) - - -(7) cppunit 1.9.14 or later. http://cppunit.sourceforge.net - -Unit testing framework for C++. - - -(8) Simple Wrapper Interface Generator. http://www.swig.org - -As of repository version 4045, gnuradio requires version 1.3.31 or newer. - - -(9) GNU Scientific Library (gsl) 1.10 or later - -The GNU Radio core library uses some routines from here. - - -Optional, but nice to have: - -(10) wxPython. Python binding for the wxWidgets GUI framework. Use -version 2.8 or later. Again, almost all systems have this -available. - -As a last resort, build it from source (not recommended!) -http://www.wxpython.org - -(11) xmlto version ? or later. http://cyberelk.net/tim/xmlto/index.html - -Wrapper for XML conversion tools to ease e.g. making html from docbook. - -(12) Python Cheetah extensions 2.0.0 or later -(13) Python lxml wrappers 2.0.0 or later -(14) Python gtk wrappers 2.10.0 or later - -The GNU Radio Companion application requires these additional Python libraries -to be installed. - -The gr-qtgui requires these packages: - -(15) Qt 4.4 or later -(16) Qwt 5.2 or later -(17) PyQt 4.4 or later -(18) PyQwt 5.2 or later - -It is also useful to have Python's Scipy and Matplot lib packages to -run some of the example. - ----------------------------------------------------------------- - -If you have doxygen installed, the build process creates -documentation for the class hierarchy etc. Point your browser at -gnuradio/gnuradio-core/doc/html/index.html - - To run the examples you may need to set PYTHONPATH. Note that the prefix and python version number in the path needs to match your installed version of python. - $ export PYTHONPATH=/usr/local/lib/python2.5/site-packages + $ export PYTHONPATH=/usr/local/lib/python2.7/dist-packages You may want to add this to your shell init file (~/.bash_profile if you use bash). - Another handy trick if for example your fftw includes and libs are installed in, say ~/local/include and ~/local/lib, instead of /usr/local is this: diff --git a/cmake/Modules/FindSphinx.cmake b/cmake/Modules/FindSphinx.cmake new file mode 100644 index 000000000..da12ee93d --- /dev/null +++ b/cmake/Modules/FindSphinx.cmake @@ -0,0 +1,37 @@ +# - This module looks for Sphinx +# Find the Sphinx documentation generator +# +# This modules defines +# SPHINX_EXECUTABLE +# SPHINX_FOUND + +#============================================================================= +# Copyright 2002-2009 Kitware, Inc. +# Copyright 2009-2011 Peter Colberg +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file COPYING-CMAKE-SCRIPTS for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +find_program(SPHINX_EXECUTABLE NAMES sphinx-build + HINTS + $ENV{SPHINX_DIR} + PATH_SUFFIXES bin + DOC "Sphinx documentation generator" +) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(Sphinx DEFAULT_MSG + SPHINX_EXECUTABLE +) + +mark_as_advanced( + SPHINX_EXECUTABLE +) diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index f67fdd7a8..24bf2405e 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -21,12 +21,14 @@ # Setup dependencies ######################################################################## find_package(Doxygen) +find_package(Sphinx) ######################################################################## # Register component ######################################################################## include(GrComponent) GR_REGISTER_COMPONENT("doxygen" ENABLE_DOXYGEN DOXYGEN_FOUND) +GR_REGISTER_COMPONENT("sphinx" ENABLE_SPHINX SPHINX_FOUND) ######################################################################## # Begin conditional configuration @@ -48,3 +50,25 @@ CPACK_COMPONENT("docs" add_subdirectory(doxygen) endif(ENABLE_DOXYGEN) + + +######################################################################## +# Begin conditional configuration +######################################################################## +if(ENABLE_SPHINX) + +######################################################################## +# Setup CPack components +######################################################################## +include(GrPackage) +CPACK_COMPONENT("docs" + DISPLAY_NAME "Documentation" + DESCRIPTION "Sphinx generated documentation" +) + +######################################################################## +# Add subdirectories +######################################################################## +add_subdirectory(sphinx) + +endif(ENABLE_SPHINX) diff --git a/docs/doxygen/doxyxml/doxyindex.py b/docs/doxygen/doxyxml/doxyindex.py index 0132ab86f..304109a8e 100644 --- a/docs/doxygen/doxyxml/doxyindex.py +++ b/docs/doxygen/doxyxml/doxyindex.py @@ -1,23 +1,23 @@ # # 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. -# +# """ Classes providing more user-friendly interfaces to the doxygen xml docs than the generated classes provide. @@ -40,7 +40,7 @@ class DoxyIndex(Base): if self._parsed: return super(DoxyIndex, self)._parse() - self._root = index.parse(os.path.join(self._xml_path, 'index.xml')) + self._root = index.parse(os.path.join(self._xml_path, 'index.xml')) for mem in self._root.compound: converted = self.convert_mem(mem) # For files we want the contents to be accessible directly @@ -78,7 +78,24 @@ class DoxyCompMem(Base): bd = description(getattr(parse_data, 'briefdescription', None)) dd = description(getattr(parse_data, 'detaileddescription', None)) self._data['brief_description'] = bd - self._data['detailed_description'] = dd + 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 @@ -86,7 +103,6 @@ class DoxyCompound(DoxyCompMem): class DoxyMember(DoxyCompMem): pass - class DoxyFunction(DoxyMember): __module__ = "gnuradio.utils.doxyxml" @@ -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']) @@ -111,7 +130,7 @@ Base.mem_classes.append(DoxyFunction) class DoxyParam(DoxyMember): - + __module__ = "gnuradio.utils.doxyxml" def _parse(self): @@ -121,16 +140,46 @@ 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 DoxyClass(DoxyCompound): +class DoxyParameterItem(DoxyMember): + """A different representation of a parameter in Doxygen.""" + + def _parse(self): + if self._parsed: + return + super(DoxyParameterItem, self)._parse() + names = [] + for nl in self._parse_data.parameternamelist: + for pn in nl.parametername: + names.append(description(pn)) + # Just take first name + self._data['name'] = names[0] + # Get description + pd = description(self._parse_data.get_parameterdescription()) + self._data['description'] = pd + + description = property(lambda self: self.data()['description']) + name = property(lambda self: self.data()['name']) + +class DoxyClass(DoxyCompound): + __module__ = "gnuradio.utils.doxyxml" kind = 'class' - + def _parse(self): if self._parsed: return @@ -139,22 +188,24 @@ class DoxyClass(DoxyCompound): if self._error: return self.set_descriptions(self._retrieved_data.compounddef) + self.set_parameters(self._retrieved_data.compounddef) # Sectiondef.kind tells about whether private or public. # We just ignore this for now. self.process_memberdefs() 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']) Base.mem_classes.append(DoxyClass) - + class DoxyFile(DoxyCompound): - + __module__ = "gnuradio.utils.doxyxml" kind = 'file' - + def _parse(self): if self._parsed: return @@ -164,7 +215,7 @@ class DoxyFile(DoxyCompound): if self._error: return self.process_memberdefs() - + brief_description = property(lambda self: self.data()['brief_description']) detailed_description = property(lambda self: self.data()['detailed_description']) @@ -172,16 +223,16 @@ Base.mem_classes.append(DoxyFile) class DoxyNamespace(DoxyCompound): - + __module__ = "gnuradio.utils.doxyxml" kind = 'namespace' - + Base.mem_classes.append(DoxyNamespace) class DoxyGroup(DoxyCompound): - + __module__ = "gnuradio.utils.doxyxml" kind = 'group' @@ -209,7 +260,7 @@ class DoxyGroup(DoxyCompound): self.process_memberdefs() title = property(lambda self: self.data()['title']) - + Base.mem_classes.append(DoxyGroup) @@ -224,7 +275,7 @@ Base.mem_classes.append(DoxyFriend) class DoxyOther(Base): - + __module__ = "gnuradio.utils.doxyxml" kinds = set(['variable', 'struct', 'union', 'define', 'typedef', 'enum', 'dir', 'page']) @@ -232,6 +283,6 @@ class DoxyOther(Base): @classmethod def can_parse(cls, obj): return obj.kind in cls.kinds - + Base.mem_classes.append(DoxyOther) diff --git a/docs/doxygen/other/build_guide.dox b/docs/doxygen/other/build_guide.dox index 780976d62..629a0f89f 100644 --- a/docs/doxygen/other/build_guide.dox +++ b/docs/doxygen/other/build_guide.dox @@ -19,13 +19,16 @@ components is determined by what the user requires from GNU Radio. If, for example, you do not use any Comedi-based hardware, do not worry about building gr-comedi. +Before trying to build these from source, please try your system's +installation tool (apt-get, pkg_install, YaST, yum, urpmi, etc.) +first. Most recent systems have these packages available. + \subsection dep_global Global Dependencies \li git http://code.google.com/p/msysgit \li cmake (>= 2.6) http://www.cmake.org/cmake/resources/software.html \li boost (>= 1.35) http://www.boostpro.com/download \li cppunit (>= 1.9.14) http://gaiacrtn.free.fr/cppunit/index.html \li fftw3f (>= 3.0) http://www.fftw.org/install/windows.html -\li gsl (>= 1.10) http://gnuwin32.sourceforge.net/packages/gsl.htm \subsection dep_python Python Wrappers \li python (>= 2.5) http://www.python.org/download/ @@ -39,6 +42,9 @@ about building gr-comedi. \li Cheetah (>= 2.0) http://www.cheetahtemplate.org/ \li pygtk (>= 2.10) http://www.pygtk.org/downloads.html +\subsection dep_wavelet gr-wavelet: Collection of wavelet blocks +\li gsl (>= 1.10) http://gnuwin32.sourceforge.net/packages/gsl.htm + \subsection dep_gr_qtgui gr-qtgui: The QT-based Graphical User Interface \li qt (>= 4.4) http://qt.nokia.com/downloads/ \li qwt (>= 5.2) http://sourceforge.net/projects/qwt/ @@ -57,6 +63,10 @@ about building gr-comedi. \li audio-osx \li audio-windows +It is not necessary to satisfy all of these dependencies; just the +one(s) that are right for your system. On Linux, don't expect +audio-osx and audio-windows to be either satisfied or built. + \subsection dep_uhd uhd: The Ettus USRP Hardware Driver Interface \li uhd (>= 3.0.0) http://code.ettus.com/redmine/ettus/projects/uhd/wiki @@ -146,23 +156,3 @@ cmake -DCMAKE_CXX_FLAGS:STRING="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -g -DCMAKE_C_FLAGS:STRING="-mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -g" \ <gr_source_dir> \endcode - - -\section build_old_autotools Building Using Old Autotools Method - -As of version 3.5, we have moved to using Cmake as the default, -preferred build system. If for some reason, Cmake fails on your -system, GNU Radio still includes the old autotools build process as a -parallel build method. To build: - -\code -$ cd $(srcdir) -$ ./bootstrap // only if not building from a tarball -$ cd $(builddir) -$ $(srcdir)/configure [options] -$ make [-jN] -$ make check -$ sudo make install -\endcode - -*/ diff --git a/docs/doxygen/swig_doc.py b/docs/doxygen/swig_doc.py index bd35b8efd..927747098 100644 --- a/docs/doxygen/swig_doc.py +++ b/docs/doxygen/swig_doc.py @@ -1,23 +1,23 @@ # # 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. -# +# """ Creates the swig_doc.i SWIG interface file. Execute using: python swig_doc.py xml_path outputfilename @@ -29,11 +29,8 @@ python docstrings. import sys, time -try: - from doxyxml import DoxyIndex, DoxyClass, DoxyFriend, DoxyFunction, DoxyFile, base -except ImportError: - from gnuradio.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('_') @@ -56,8 +53,29 @@ class Block(object): # Check for a parsing error. if item.error(): return False - return item.has_member(make_name(item.name()), DoxyFriend) - + 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): """ @@ -82,13 +100,19 @@ def combine_descriptions(obj): if dd: description.append(dd) return utoascii('\n\n'.join(description)).strip() - + +def format_params(parameteritems): + output = ['Args:'] + template = ' {0} : {1}' + for pi in parameteritems: + output.append(template.format(pi.name, pi.description)) + return '\n'.join(output) entry_templ = '%feature("docstring") {name} "{docstring}"' -def make_entry(obj, name=None, templ="{description}", description=None): +def make_entry(obj, name=None, templ="{description}", description=None, params=[]): """ Create a docstring entry for a swig interface file. - + obj - a doxyxml object from which documentation will be extracted. name - the name of the C object (defaults to obj.name()) templ - an optional template for the docstring containing only one @@ -102,6 +126,9 @@ def make_entry(obj, name=None, templ="{description}", description=None): return '' if description is None: description = combine_descriptions(obj) + if params: + description += '\n\n' + description += utoascii(format_params(params)) docstring = templ.format(description=description) if not docstring: return '' @@ -121,27 +148,31 @@ def make_func_entry(func, name=None, description=None, params=None): used as the description instead of extracting it from func. params - a parameter list that overrides using func.params. """ - if params is None: - params = func.params - params = [prm.declname for prm in params] - if params: - sig = "Params: (%s)" % ", ".join(params) - else: - sig = "Params: (NONE)" - templ = "{description}\n\n" + sig - return make_entry(func, name=name, templ=utoascii(templ), - description=description) - - -def make_class_entry(klass, description=None): + #if params is None: + # params = func.params + #params = [prm.declname for prm in params] + #if params: + # sig = "Params: (%s)" % ", ".join(params) + #else: + # sig = "Params: (NONE)" + #templ = "{description}\n\n" + sig + #return make_entry(func, name=name, templ=utoascii(templ), + # description=description) + return make_entry(func, name=name, description=description, params=params) + + +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)) + 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) @@ -175,18 +206,56 @@ 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=creator.params)) + 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 make_swig_interface_file(di, swigdocfilename, custom_output=None): +def wait_if_necessary(tries, swigdocfilename, item=None): + if item is not None: + extra = ', item {0}'.format(item.name()) + else: + extra = '' + if(tries < 3): + # May not be built just yet; sleep and try again + sys.stderr.write("XML parsing problem with file {0}{1}, retrying.\n".format( + swigdocfilename, extra)) + time.sleep(1) + tries += 1 + return tries, True + else: + # if we've given it three tries, give up and raise an error + sys.stderr.write("XML parsing error with file {0}{1}. giving up.\n".format( + swigdocfilename, extra)) + return tries, False +def make_swig_interface_file(di, swigdocfilename, custom_output=None, tries=0): + output = [""" /* * This file was automatically generated using swig_doc.py. - * + * * Any changes to it will be lost next time it is regenerated. */ """] @@ -195,67 +264,71 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None): output.append(custom_output) # Create docstrings for the blocks. - tries = 0 while(1): try: blocks = di.in_category(Block) + blocks2 = di.in_category(Block2) except: - if(tries < 3): - # May not be built just yet; sleep and try again - sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format( - swigdocfilename)) - time.sleep(1) - tries += 1 - else: - # if we've given it three tries, give up and raise an error - sys.stderr.write("XML parsing error with file {0}. giving up.\n".format( - swigdocfilename)) + tries, try_again = wait_if_necessary(tries, swigdocfilename) + if not try_again: raise else: break - make_funcs = set([]) for block in blocks: - tries = 0 while(1): try: make_func = di.get_member(make_name(block.name()), DoxyFunction) - make_funcs.add(make_func.name()) - output.append(make_block_entry(di, block)) + # 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_block_entry(di, block)) except block.ParsingError: - sys.stderr.write('Parsing error for block {0}'.format(block.name())) + sys.stderr.write('Parsing error for block {0}\n'.format(block.name())) except: - if(tries < 3): - # May not be built just yet; sleep and try again - sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format( - swigdocfilename)) - time.sleep(1) - tries += 1 - else: - # if we've given it three tries, give up and raise an error - sys.stderr.write("XML parsing error with file {0}. giving up.\n".format( - swigdocfilename)) + tries, try_again = wait_if_necessary(tries, swigdocfilename, block) + if not try_again: 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)) except f.ParsingError: - sys.stderr.write('Parsing error for function {0}'.format(f.name())) + sys.stderr.write('Parsing error for function {0}\n'.format(f.name())) # 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)) except k.ParsingError: - sys.stderr.write('Parsing error for class {0}'.format(k.name())) + sys.stderr.write('Parsing error for class {0}\n'.format(k.name())) # Docstrings are not created for anything that is not a function or a class. # If this excludes anything important please add it here. @@ -291,19 +364,11 @@ if __name__ == "__main__": tries = 0 while(1): try: - make_swig_interface_file(di, swigdocfilename, custom_output=custom_output) + make_swig_interface_file(di, swigdocfilename, custom_output=custom_output, tries=tries) except: - if(tries < 3): - # May not be built just yet; sleep and try again - sys.stderr.write("XML parsing problem with file {0}, retrying.\n".format( - swigdocfilename)) - time.sleep(1) - tries += 1 - else: - # if we've given it three tries, give up and raise an error - sys.stderr.write("XML parsing error with file {0}. giving up.\n".format( - swigdocfilename)) + tries, try_again = wait_if_necessary(tries, swigdocfilename) + if not try_again: raise else: break - + diff --git a/docs/sphinx/CMakeLists.txt b/docs/sphinx/CMakeLists.txt new file mode 100644 index 000000000..38d77fb3a --- /dev/null +++ b/docs/sphinx/CMakeLists.txt @@ -0,0 +1,35 @@ +# 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) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/source/conf.py.in + ${CMAKE_CURRENT_BINARY_DIR}/conf.py +@ONLY) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/run_sphinx_build.sh.in + ${CMAKE_BINARY_DIR}/run_sphinx_build.sh +@ONLY) + +if(UNIX) + #make the shell file executable + execute_process(COMMAND chmod +x ${CMAKE_BINARY_DIR}/run_sphinx_build.sh) +endif(UNIX) diff --git a/docs/sphinx/README b/docs/sphinx/README new file mode 100644 index 000000000..0ae3a43f8 --- /dev/null +++ b/docs/sphinx/README @@ -0,0 +1,72 @@ +INTRODUCTION +The Sphinx documentation system uses the fully installed Python tree +to build a set of documents (generally in HTML). In GNU Radio, the +documentation system is done through Doxygen in the public header +(/include/foo.h) files. Doxygen first builds its documentation files, +then the swig_docs program uses Doxygen's XML output and smashed the +documentation from each header file into the SWIG'd Python +block. Basically, using a single documentation markup, Doxygen, we +expose the documentation strings in both the Doxygen-built manual and +within the Python blocks themselves. + +Sphinx takes this process one step farther by reading the docstrings +of all Python blocks and creating its own manual. This has two +benefits. First, the Sphinx documentation looks nice and is formatted +in such a way that Python users of GNU Radio can easy see the module +structure and hierarchy. It also not only takes the Doxygen +documentation from C++, but it also allows us to take any Python files +and include their documentation. + +The end result is two manuals: one for Python and one for C++ users +without having to duplicate comments, markup, or documentation. + + +BUILDING THE SPHINX MANUAL +Building the Sphinx docs takes some manual intervention as it +requires GNU Radio to already be installed. So first follow the steps +to build and install GNU Radio. + +In the build directory, a helper file is created called +run_sphinx_build.sh. This is a Linux shell script that runs the +sphinx-build command with all of the normal settings and important +directories preloaded. For non Linux systems, it should be easy to +pull out the executable and options to run it by hand. + +The run_sphinx_build.sh outputs the manual into +$builddir/docs/sphinx/sphinx_out. Open up the index.html file in a +browser to view it. + +ADDING NEW CONTENT TO THE SPHINX MANUAL +Although the content of the sphinx manual is automatically generated, +new blocks are not automatically added to the generated documentation. +The procedure for adding new content is best illustrated with two +examples. + +1) Adding a new C++ signal processing block gnuradio.gr.myslicer + Edit file gnuradio/docs/sphinx/source/gr/index.rst and add the line + > gnuradio.gr.myslicer + under the "Slicing and Dicing Streams" subheading. + Edit file gnuradio/docs/sphinx/source/gr/slicedice_blk.rst and add + the line + >.. 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 + line + > gnuradio.digital.mymod + under the "Signal Processing Blocks" subheading. + Edit file gnuradio/docs/sphinx/source/digital/blocks.rst and add + the line + >.. autopyblock:: gnuradio.digital.mymod + Notice that the 'autopyblock' directive is used rather than the + 'autoblock' directive. This lets sphinx know that it is displaying + 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 '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 new file mode 100644 index 000000000..e8ca867f8 --- /dev/null +++ b/docs/sphinx/gnuradio_sphinx.py @@ -0,0 +1,183 @@ +""" +Customizations of sphinx for gnuradio use. +""" + +from sphinx.ext.autodoc import py_ext_sig_re +from sphinx.ext.autodoc import ClassDocumenter, FunctionDocumenter, members_option +from sphinx.ext.autodoc import bool_option, members_set_option, identity +from sphinx.ext.autodoc import ALL + +# A dictionary of the number of lines to delete from the beginning of docstrings +lines_to_delete = {} + +def setup(sp): + # Fix line-breaks in signature. + 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) + +def remove_lines(app, what, name, obj, options, lines): + del_lines = lines_to_delete.get(name, 0) + # Don't delete any lines if this is called again. + lines_to_delete[name] = 0 + lines[:] = lines[del_lines:] + +def fix_signature(app, what, name, obj, options, signature, return_annotation): + """ + SWIG produces signature at the top of docstrings of the form + 'blah(int arg1, float arg2) -> return_type' + and if the string is long it breaks it over multiple lines. + + Sphinx gets confused if it is broken over multiple lines. + fix_signature and remove_lines get around this problem. + """ + if return_annotation is not None: + return + + if hasattr(obj, '__doc__'): + docs = obj.__doc__ + else: + docs = None + if not docs: + return None + doclines = docs.split('\n') + del_lines = remove_linebreaks_in_signature(doclines) + # match first line of docstring against signature RE + match = py_ext_sig_re.match(doclines[0]) + if not match: + return None + exmod, path, base, args, retann = match.groups() + # ok, now jump over remaining empty lines and set the remaining + # lines as the new doclines + i = 1 + while i < len(doclines) and not doclines[i].strip(): + i += 1 + lines_to_delete[name] = i - 1 + del_lines + # format args + signature = "({0})".format(args) + return signature, retann + +def remove_linebreaks_in_signature(lines): + alllines = '\n'.join(lines) + alllines = alllines.lstrip() + bits = alllines.split('->') + if len(bits) == 1: + return 0 + after = '->'.join(bits[1:]) + after_lines = after.split('\n') + ending = None + remainder = [] + for line in after_lines: + if line and ending is None: + ending = line + elif ending is not None: + remainder.append(line) + first_line = ' '.join([a.strip() for a in bits[0].split('\n') if a.strip()]) + ' -> ' + ending.strip() + match = py_ext_sig_re.match(first_line) + # If it is a signature, make the change to lines. + if match: + new_lines = [first_line] + remainder + lines[:] = new_lines + return len(bits[0].split('\n')) + else: + return 0 + +# These methods are not displayed in the documentation of blocks to +# avoid redundancy. +common_block_members =[ + 'check_topology', + 'detail', + 'history', + 'input_signature', + 'name', + 'nitems_read', + 'nitems_written', + 'nthreads', + 'output_multiple', + 'output_signature', + 'relative_rate', + 'set_detail', + 'set_nthreads', + 'start', + 'stop', + 'thisown', + 'to_basic_block', + 'unique_id', + 'make', + ] + +class OldBlockDocumenter(FunctionDocumenter): + """ + Specialized Documenter subclass for gnuradio blocks. + + It merges together the documentation for the generator function (e.g. gr.head) + with the wrapped sptr (e.g. gr.gr_head_sptr) to keep the documentation + tidier. + """ + 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(OldBlockDocumenter, self).__init__(*args, **kwargs) + # Get class name + bits = self.name.split('.') + if len(bits) != 3 or bits[0] != 'gnuradio': + raise ValueError("expected name to be of form gnuradio.x.y but it is {0}".format(self.name)) + 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 + self.classdoccer.parse_name() + self.classdoccer.import_object() + + def document_members(self, *args, **kwargs): + return self.classdoccer.document_members(*args, **kwargs) + +class PyBlockDocumenter(ClassDocumenter): + """ + Specialized Documenter subclass for hierarchical python gnuradio blocks. + """ + objtype = 'pyblock' + directivetype = 'class' + + def __init__(self, *args, **kwargs): + super(PyBlockDocumenter, self).__init__(*args, **kwargs) + self.options.members = ALL + self.options.exclude_members = common_block_members diff --git a/docs/sphinx/hieroglyph/LICENSE.txt b/docs/sphinx/hieroglyph/LICENSE.txt new file mode 100644 index 000000000..3f7a63830 --- /dev/null +++ b/docs/sphinx/hieroglyph/LICENSE.txt @@ -0,0 +1,26 @@ +Copyright (c) 2011, Robert Smallshire +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Robert Smallshire nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/sphinx/hieroglyph/README.txt b/docs/sphinx/hieroglyph/README.txt new file mode 100644 index 000000000..c26409d89 --- /dev/null +++ b/docs/sphinx/hieroglyph/README.txt @@ -0,0 +1,10 @@ +Sphinx is a popular tool for documenting Python APIs which uses reStructuredText +as a its lightweight markup language. Sphinx extends restructured text with +semantic markup elements for documenting Python APIs but once these are used the +ratio of markup to content becomes too high and readability is compromised +enough that the docstring becomes unsuitable for use with standard Python +introspection mechanisms like help() or IDEs. + +Hieroglyph is an a Sphinx extension which automatically converts a highly +readable docstring format suitable for use with help() and IDEs to the +reStructuredText hieroglyphics required by Sphinx.
\ No newline at end of file diff --git a/docs/sphinx/hieroglyph/__init__.py b/docs/sphinx/hieroglyph/__init__.py new file mode 100644 index 000000000..25dea27fb --- /dev/null +++ b/docs/sphinx/hieroglyph/__init__.py @@ -0,0 +1,6 @@ +# We only need to expose the setup function to Sphinx + +from .hieroglyph import setup +from .version import __version__ + +__author__ = 'Robert Smallshire'
\ No newline at end of file diff --git a/docs/sphinx/hieroglyph/errors.py b/docs/sphinx/hieroglyph/errors.py new file mode 100644 index 000000000..334b097d8 --- /dev/null +++ b/docs/sphinx/hieroglyph/errors.py @@ -0,0 +1,10 @@ +
+from sphinx.errors import ExtensionError
+
+__author__ = 'rjs'
+
+class HieroglyphError(ExtensionError):
+ '''
+ An exception type specific to the Hieroglyph Sphinx extension.
+ '''
+ pass
\ No newline at end of file diff --git a/docs/sphinx/hieroglyph/hieroglyph.py b/docs/sphinx/hieroglyph/hieroglyph.py new file mode 100644 index 000000000..0056d9ab8 --- /dev/null +++ b/docs/sphinx/hieroglyph/hieroglyph.py @@ -0,0 +1,404 @@ +from __future__ import print_function + +import re + +from errors import HieroglyphError +from nodes import (Node, Raises, Except, Note, Warning, Returns, Arg, + ensure_terminal_blank) + +__author__ = 'Robert Smallshire' + +def parse_hieroglyph_text(lines): + '''Parse text in hieroglyph format and return a reStructuredText equivalent + + Args: + lines: A sequence of strings representing the lines of a single + docstring as read from the source by Sphinx. This string should be + in a format that can be parsed by hieroglyph. + + Returns: + A list of lines containing the transformed docstring as + reStructuredText as produced by hieroglyph. + + Raises: + RuntimeError: If the docstring cannot be parsed. + ''' + indent_lines = unindent(lines) + indent_lines = pad_blank_lines(indent_lines) + indent_lines = first_paragraph_indent(indent_lines) + indent_paragraphs = gather_lines(indent_lines) + parse_tree = group_paragraphs(indent_paragraphs) + syntax_tree = extract_structure(parse_tree) + result = syntax_tree.render_rst() + ensure_terminal_blank(result) + return result + + +def unindent(lines): + '''Convert an iterable of indented lines into a sequence of tuples. + + The first element of each tuple is the indent in number of characters, and + the second element is the unindented string. + + Args: + lines: A sequence of strings representing the lines of text in a docstring. + + Returns: + A list of tuples where each tuple corresponds to one line of the input + list. Each tuple has two entries - the first is an integer giving the + size of the indent in characters, the second is the unindented text. + ''' + unindented_lines = [] + for line in lines: + unindented_line = line.lstrip() + indent = len(line) - len(unindented_line) + unindented_lines.append((indent, unindented_line)) + return unindented_lines + + +def pad_blank_lines(indent_texts): + '''Give blank (empty) lines the same indent level as the preceding line. + + Args: + indent_texts: An iterable of tuples each containing an integer in the + first element and a string in the second element. + + Returns: + A list of tuples each containing an integer in the first element and a + string in the second element. + ''' + current_indent = 0 + result = [] + for indent, text in indent_texts: + if len(text) > 0: + current_indent = indent + result.append((current_indent, text)) + return result + + +def extract_structure(parse_tree): + '''Create an Abstract Syntax Tree representing the semantics of a parse tree. + + Args: + parse_tree: TODO + + Returns: + A Node with is the result of an Abstract Syntax Tree representing the + docstring. + + Raises: + HieroglyphError: In the event that the parse tree cannot be understood. + ''' + return convert_node(parse_tree) + + +def convert_node(node): + if node.indent == 0 and len(node.lines) == 0: + return convert_children(node) + if node.lines[0].startswith('Args:'): + return convert_args(node) + if node.lines[0].startswith('Returns:'): + return convert_returns(node) + if node.lines[0].startswith('Raises:'): + return convert_raises(node) + if node.lines[0].startswith('Note:'): + return convert_note(node) + if node.lines[0].startswith('Warning:'): + return convert_warning(node) + result = convert_children(node) + result.lines = node.lines + result.indent = node.indent + return result + + +def convert_children(node): + converted_children = [convert_node(child) for child in node.children] + result = Node() + result.children = converted_children + return result + + +ARG_REGEX = re.compile(r'(\*{0,2}\w+)(\s+\((\w+)\))?\s*:\s*(.*)') + +def append_child_to_args_group_node(child, group_node, indent): + arg = None + non_empty_lines = (line for line in child.lines if line) + for line in non_empty_lines: + m = ARG_REGEX.match(line) + if m is None: + raise HieroglyphError("Invalid hieroglyph argument syntax: {0}".format(line)) + param_name = m.group(1) + param_type = m.group(3) + param_text = m.group(4) + + arg = Arg(indent, child.indent, param_name) + group_node.children.append(arg) + arg.type = param_type + + if param_text is not None: + arg.children.append(Node(indent, [param_text], arg)) + if arg is not None: + last_child = arg.children[-1] if len(arg.children) != 0 else arg + for grandchild in child.children: + last_child.children.append(grandchild) + + +def convert_args(node): + assert node.lines[0].startswith('Args:') + group_node = Node() + for child in node.children: + append_child_to_args_group_node(child, group_node, node.indent) + return group_node + + +def convert_returns(node): + assert node.lines[0].startswith('Returns:') + returns = Returns(node.indent) + returns.line = node.lines[0][8:].strip() + returns.children = node.children + return returns + + +def convert_note(node): + assert node.lines[0].startswith('Note:') + note = Note(node.indent) + note.line = node.lines[0][5:].strip() + note.children = node.children + return note + + +def convert_warning(node): + assert node.lines[0].startswith('Warning:') + warning = Warning(node.indent) + warning.line = node.lines[0][8:].strip() + warning.children = node.children + return warning + + +def convert_raises(node): + assert node.lines[0].startswith('Raises:') + group_node = Raises(node.indent) + for child in node.children: + append_child_to_raise_node(child, group_node) + return group_node + + +RAISE_REGEX = re.compile(r'(\w+)\s*:\s*(.*)') + +def extract_exception_type_and_text(line): + m = RAISE_REGEX.match(line) + if m is None: + raise HieroglyphError("Invalid hieroglyph exception syntax: {0}".format(line)) + return (m.group(2), m.group(1)) + + +def append_child_to_raise_node(child, group_node): + exception = None + non_empty_lines = (line for line in child.lines if line) + for line in non_empty_lines: + exception_text, exception_type = extract_exception_type_and_text(line) + + exception = Except(child.indent, exception_type) + group_node.children.append(exception) # TODO: Could use parent here. + + if exception_text is not None: + exception.children.append( Node(child.indent, + [exception_text], exception)) + if exception is not None: + last_child = exception.children[-1] if len(exception.children) != 0 else exception + for grandchild in child.children: + last_child.children.append(grandchild) + + +def group_paragraphs(indent_paragraphs): + ''' + Group paragraphs so that more indented paragraphs become children of less + indented paragraphs. + ''' + # The tree consists of tuples of the form (indent, [children]) where the + # children may be strings or other tuples + + root = Node(0, [], None) + current_node = root + + previous_indent = -1 + for indent, lines in indent_paragraphs: + if indent > previous_indent: + current_node = create_child_node(current_node, indent, lines) + elif indent == previous_indent: + current_node = create_sibling_node(current_node, indent, lines) + elif indent < previous_indent: + current_node = create_uncle_node(current_node, indent, lines) + previous_indent = indent + return root + + +def create_sibling_node(current_node, indent, lines): + sibling = Node(indent, lines, current_node.parent) + current_node.parent.add_child(sibling) + current_node = sibling + return current_node + + +def create_child_node(current_node, indent, lines): + child = Node(indent, lines, current_node) + current_node.add_child(child) + current_node = child + return current_node + + +def create_uncle_node(current_node, indent, lines): + ancestor = current_node + while ancestor.indent >= indent: + if ancestor.parent is None: + break + ancestor = ancestor.parent + uncle = Node(indent, lines, ancestor) + ancestor.add_child(uncle) + current_node = uncle + return current_node + + +def gather_lines(indent_lines): + '''Split the list of (int, str) tuples into a list of (int, [str]) tuples + to group the lines into paragraphs of consistent indent. + ''' + return remove_empty_paragraphs(split_separated_lines(gather_lines_by_indent(indent_lines))) + +def gather_lines_by_indent(indent_lines): + result = [] + previous_indent = -1 + for indent, line in indent_lines: + if indent != previous_indent: + paragraph = (indent, []) + result.append(paragraph) + else: + paragraph = result[-1] + paragraph[1].append(line) + previous_indent = indent + return result + +def split_separated_lines(indent_paragraphs): + result = [] + for indent, paragraph in indent_paragraphs: + result.append((indent, [])) + + if len(paragraph) > 0: + result[-1][1].append(paragraph[0]) + + if len(paragraph) > 2: + for line in paragraph[1: -1]: + result[-1][1].append(line) + if len(line) == 0: + result.append((indent, [])) + + if len(paragraph) > 1: + result[-1][1].append(paragraph[-1]) + + return result + +def remove_empty_paragraphs(indent_paragraphs): + return [(indent, paragraph) for indent, paragraph in indent_paragraphs if len(paragraph)] + +def first_paragraph_indent(indent_texts): + '''Fix the indentation on the first paragraph. + + This occurs because the first line of a multi-line docstring following the + opening quote usually has no indent. + + Args: + indent_texts: The lines of the docstring as an iterable over 2-tuples + each containing an integer indent level as the first element and + the text as the second element. + + Return: + A list of 2-tuples, each containing an integer indent level as the + first element and the text as the second element. + ''' + opening_indent = determine_opening_indent(indent_texts) + + result = [] + input = iter(indent_texts) + for indent, text in input: + if indent == 0: + result.append((opening_indent, text)) + else: + result.append((indent, text)) + break + + for indent, text in input: + result.append((indent, text)) + + return result + + +def determine_opening_indent(indent_texts): + '''Determine the opening indent level for a docstring. + + The opening indent level is the indent level is the first non-zero indent + level of a non-empty line in the docstring. + + Args: + indent_texts: The lines of the docstring as an iterable over 2-tuples + each containing an integer indent level as the first element and + the text as the second element. + + Returns: + The opening indent level as an integer. + ''' + num_lines = len(indent_texts) + + if num_lines < 1: + return 0 + + assert num_lines >= 1 + + first_line_indent = indent_texts[0][0] + + if num_lines == 1: + return first_line_indent + + assert num_lines >= 2 + + second_line_indent = indent_texts[1][0] + second_line_text = indent_texts[1][1] + + if len(second_line_text) == 0: + return first_line_indent + + return second_line_indent + + + +def rewrite_autodoc(app, what, name, obj, options, lines): + '''Convert lines from Hieroglyph to Sphinx format. + + The function to be called by the Sphinx autodoc extension when autodoc + has read and processed a docstring. This function modified its + ``lines`` argument *in place* replacing Hieroglyph syntax input into + Sphinx reStructuredText output. + + Args: + apps: The Sphinx application object. + + what: The type of object which the docstring belongs to. One of + 'module', 'class', 'exception', 'function', 'method', 'attribute' + + name: The fully qualified name of the object. + + obj: The object itself. + + options: The options given to the directive. An object with attributes + ``inherited_members``, ``undoc_members``, ``show_inheritance`` and + ``noindex`` that are ``True`` if the flag option of the same name + was given to the auto directive. + + lines: The lines of the docstring. Will be modified *in place*. + ''' + lines[:] = parse_hieroglyph_text(lines) + + +def setup(app): + app.connect('autodoc-process-docstring', rewrite_autodoc) + + diff --git a/docs/sphinx/hieroglyph/nodes.py b/docs/sphinx/hieroglyph/nodes.py new file mode 100644 index 000000000..e583ce04d --- /dev/null +++ b/docs/sphinx/hieroglyph/nodes.py @@ -0,0 +1,267 @@ +__author__ = 'Robert Smallshire'
+
+class Node(object):
+
+ def __init__(self, indent=None, lines=None, parent=None):
+ if indent is not None:
+ self.indent = indent
+ else:
+ self.indent = 0
+
+ if lines is not None:
+ self.lines = lines
+ else:
+ self.lines = []
+
+ self._parent = parent
+
+ self.children = []
+
+ parent = property(lambda self: self._parent)
+
+ def add_child(self, child):
+ assert(child.parent is self)
+ self.children.append(child)
+
+
+ def __repr__(self):
+ return "Node(" + repr(self.indent) + ", " + repr(self.lines) + ", children=" + repr(self.children) + ")"
+
+
+ def render_rst(self, *args, **kwargs):
+ result = []
+ prefix = ' ' * self.indent
+ result.extend(prefix + line for line in self.lines)
+ for child in self.children:
+ result.extend(child.render_rst())
+ return result
+
+
+
+class Arg(Node):
+
+ def __init__(self, indent, child_indent, name):
+ super(Arg, self).__init__(indent)
+ self.child_indent = child_indent
+ self.name = name
+ self.type = None
+
+
+ def __repr__(self):
+ return "Arg(" + repr(self.name) + ", " + repr(self.type) + ", children=" + repr(self.children) + ")"
+
+
+ def render_rst(self, *args, **kwargs):
+ result = []
+ indent = ' ' * self.indent
+
+ # Render the param description
+ description = []
+ for child in self.children:
+ child_lines = child.render_rst()
+ description.extend(child_lines)
+
+ dedent = self.child_indent - self.indent
+
+ name = self.name.replace('*', r'\*')
+
+ first_description = description[0].lstrip() if len(description) else ''
+ if not first_description:
+ # TODO: Emit a warning about a missing argument description
+ pass
+
+ result.append("{indent}:param {name}: {first_description}".format(indent=indent, name=name,
+ first_description=first_description))
+
+ dedented_body = [line[dedent:] for line in description[1:]]
+
+ result.extend(dedented_body)
+
+ # If a type was specified render the type
+ if self.type is not None:
+ result.append("{indent}:type {name}: {type}".format(indent=indent, name=self.name, type=self.type))
+ result.append('')
+
+ ensure_terminal_blank(result)
+
+ return result
+
+
+
+class Raises(Node):
+
+ def __init__(self, indent=None):
+ super(Raises, self).__init__(indent=indent)
+
+ def __repr__(self):
+ return "Raises(" + repr(self.indent) + ", children=" + repr(self.children) + ")"
+
+
+ def render_rst(self, *args, **kwargs):
+ result = []
+ indent = ' ' * self.indent
+ result.append(indent + ':raises:')
+ for child in self.children:
+ result.extend(child.render_rst(only_child=len(self.children) == 1))
+
+ ensure_terminal_blank(result)
+
+ return result
+
+
+class Except(Node):
+
+ def __init__(self, indent, type):
+ super(Except, self).__init__(indent=indent)
+ #self.child_indent = child_indent
+ self.type = type
+
+
+ def __repr__(self):
+ return "Except(" + repr(self.type) + ", children=" + repr(self.children) + ")"
+
+
+ def render_rst(self, only_child=False, *args, **kwargs):
+ result = []
+ indent = ' ' * self.indent
+
+ # Render the param description
+ description = []
+ for child in self.children:
+ child_lines = child.render_rst()
+ description.extend(child_lines)
+
+ #dedent = self.child_indent - self.indent
+ bullet = '* ' if not only_child else ''
+
+ first_description = description[0].lstrip() if len(description) else ''
+ result.append("{indent}{bullet}{type} - {first_description}".format(indent=indent,
+ bullet=bullet, type=self.type,
+ first_description=first_description))
+
+ #dedented_body = [' ' * len(bullet) + line[dedent:] for line in description[1:]]
+ #result.extend(dedented_body)
+ result.extend(description[1:])
+ ensure_terminal_blank(result)
+
+ return result
+
+
+
+class Returns(Node):
+
+ def __init__(self, indent):
+ super(Returns, self).__init__(indent=indent)
+ self.title = 'Returns'
+ self.line = ''
+
+
+ def __repr__(self):
+ return "Returns(" + str(self.indent) + ", children=" + str(self.children) + ")"
+
+
+ def render_rst(self, *args, **kwargs):
+ result = []
+ indent = ' ' * self.indent
+
+ # Render the param description
+ description = [self.line] if self.line else []
+ for child in self.children:
+ child_lines = child.render_rst()
+ description.extend(child_lines)
+
+ self.render_title(description, indent, result)
+
+ result.extend(description[1:])
+
+ ensure_terminal_blank(result)
+ return result
+
+
+ def render_title(self, description, indent, result):
+ result.append(
+ "{indent}:returns: {first_description}".format(indent=indent,
+ first_description=description[0].lstrip()))
+
+
+
+class Warning(Node):
+
+ def __init__(self, indent):
+ super(Warning, self).__init__(indent=indent)
+
+ def __repr__(self):
+ return "Warning(" + repr(self.indent) + ", children=" + str(self.children) + ")"
+
+ def render_rst(self, *args, **kwargs):
+ # TODO: Factor out the commonality between this and Note below
+ result = []
+ indent = ' ' * self.indent
+
+ # Render the param description
+ description = [self.line] if self.line else []
+ for child in self.children:
+ child_lines = child.render_rst()
+ description.extend(child_lines)
+
+ # Fix the indent on the first line
+ if len(description) > 1 and len(description[1].strip()) != 0:
+ body_indent = len(description[1]) - len(description[1].strip())
+ else:
+ body_indent = self.indent + 4
+
+ if len(description) > 0:
+ description[0] = ' ' * body_indent + description[0]
+
+ result.append(indent + ".. warning::")
+ result.append(indent + '')
+ result.extend(description)
+
+ ensure_terminal_blank(result)
+ return result
+
+
+class Note(Node):
+
+ def __init__(self, indent):
+ super(Note, self).__init__(indent=indent)
+ self.line = ''
+
+
+ def __repr__(self):
+ return "Note(" + repr(self.indent) + ", children=" + str(self.children) + ")"
+
+
+ def render_rst(self, *args, **kwargs):
+ # TODO: Factor out the commonality between this and Warning above
+ result = []
+ indent = ' ' * self.indent
+
+ # Render the param description
+ description = [self.line] if self.line else []
+ for child in self.children:
+ child_lines = child.render_rst()
+ description.extend(child_lines)
+
+ # Fix the indent on the first line
+ if len(description) > 1 and len(description[1].strip()) != 0:
+ body_indent = len(description[1]) - len(description[1].strip())
+ else:
+ body_indent = self.indent + 4
+
+ if len(description) > 0:
+ description[0] = ' ' * body_indent + description[0]
+
+ result.append(indent + ".. note::")
+ result.append(indent + '')
+ result.extend(description)
+
+ ensure_terminal_blank(result)
+ return result
+
+
+def ensure_terminal_blank(result):
+ '''If the description didn't end with a blank line add one here.'''
+ if len(result) > 0:
+ if len(result[-1].strip()) != 0:
+ result.append('')
diff --git a/docs/sphinx/hieroglyph/test/__init__.py b/docs/sphinx/hieroglyph/test/__init__.py new file mode 100644 index 000000000..fd249423f --- /dev/null +++ b/docs/sphinx/hieroglyph/test/__init__.py @@ -0,0 +1,2 @@ +__author__ = 'rjs' +
\ No newline at end of file diff --git a/docs/sphinx/hieroglyph/test/test_comments.py b/docs/sphinx/hieroglyph/test/test_comments.py new file mode 100644 index 000000000..d1a1453ee --- /dev/null +++ b/docs/sphinx/hieroglyph/test/test_comments.py @@ -0,0 +1,586 @@ +import unittest + +from hieroglyph.hieroglyph import parse_hieroglyph_text +from hieroglyph.errors import HieroglyphError + +class CommentTests(unittest.TestCase): + + def test_comment1(self): + source = """Fetches rows from a Bigtable. + This is a continuation of the opening paragraph. + + Retrieves rows pertaining to the given keys from the Table instance + represented by big_table. Silly things may happen if + other_silly_variable is not None. + + Args: + big_table: An open Bigtable Table instance. + keys: A sequence of strings representing the key of each table row + to fetch. + other_silly_variable (str): Another optional variable, that has a much + longer name than the other args, and which does nothing. + + Returns: + A dict mapping keys to the corresponding table row data + fetched. Each row is represented as a tuple of strings. For + example: + + {'Serak': ('Rigel VII', 'Preparer'), + 'Zim': ('Irk', 'Invader'), + 'Lrrr': ('Omicron Persei 8', 'Emperor')} + + If a key from the keys argument is missing from the dictionary, + then that row was not found in the table. + + Raises: + IOError: An error occurred accessing the bigtable.Table object. + """ + + expected = """ Fetches rows from a Bigtable. + This is a continuation of the opening paragraph. + + Retrieves rows pertaining to the given keys from the Table instance + represented by big_table. Silly things may happen if + other_silly_variable is not None. + + :param big_table: An open Bigtable Table instance. + + :param keys: A sequence of strings representing the key of each table row + to fetch. + + :param other_silly_variable: Another optional variable, that has a much + longer name than the other args, and which does nothing. + + :type other_silly_variable: str + + :returns: A dict mapping keys to the corresponding table row data + fetched. Each row is represented as a tuple of strings. For + example: + + {'Serak': ('Rigel VII', 'Preparer'), + 'Zim': ('Irk', 'Invader'), + 'Lrrr': ('Omicron Persei 8', 'Emperor')} + + If a key from the keys argument is missing from the dictionary, + then that row was not found in the table. + + :raises: + IOError - An error occurred accessing the bigtable.Table object. + """ + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment2(self): + source = """Determine if all elements in the source sequence satisfy a condition. + + All of the source sequence will be consumed. + + Note: This method uses immediate execution. + + Args: + predicate: An optional single argument function used to test each + elements. If omitted, the bool() function is used resulting in + the elements being tested directly. + + Returns: + True if all elements in the sequence meet the predicate condition, + otherwise False. + + Raises: + ValueError: If the Queryable is closed() + TypeError: If predicate is not callable. + """ + + expected = """Determine if all elements in the source sequence satisfy a condition. + + All of the source sequence will be consumed. + + .. note:: + + This method uses immediate execution. + + :param predicate: An optional single argument function used to test each + elements. If omitted, the bool() function is used resulting in + the elements being tested directly. + + :returns: True if all elements in the sequence meet the predicate condition, + otherwise False. + + :raises: + * ValueError - If the Queryable is closed() + + * TypeError - If predicate is not callable. + """ + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment3(self): + source = """Determine if all elements in the source sequence satisfy a condition. + + All of the source sequence will be consumed. + + Note: This method uses immediate execution. + + Args: + predicate: An optional single argument function used to test each + elements. If omitted, the bool() function is used resulting in + the elements being tested directly. + + Returns: + True if all elements in the sequence meet the predicate condition, + otherwise False. + + Raises: + ValueError: If the Queryable is closed() + TypeError: If predicate is not callable. + """ + + expected = """Determine if all elements in the source sequence satisfy a condition. + + All of the source sequence will be consumed. + + .. note:: + + This method uses immediate execution. + + :param predicate: An optional single argument function used to test each + elements. If omitted, the bool() function is used resulting in + the elements being tested directly. + + :returns: True if all elements in the sequence meet the predicate condition, + otherwise False. + + :raises: + * ValueError - If the Queryable is closed() + + * TypeError - If predicate is not callable. + """ + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment4(self): + source_lines = [u'Determine if all elements in the source sequence satisfy a condition.', + u'', + u'All of the source sequence will be consumed.', + u'', + u'Note: This method uses immediate execution.', + u'', + u'Args:', + u' predicate: An optional single argument function used to test each', + u' elements. If omitted, the bool() function is used resulting in', + u' the elements being tested directly.', + u'', + u'Returns:', + u' True if all elements in the sequence meet the predicate condition,', + u' otherwise False.', + u'', + u'Raises:', + u' ValueError: If the Queryable is closed()', + u' TypeError: If predicate is not callable.', + u''] + + expected = """Determine if all elements in the source sequence satisfy a condition. + +All of the source sequence will be consumed. + +.. note:: + + This method uses immediate execution. + +:param predicate: An optional single argument function used to test each + elements. If omitted, the bool() function is used resulting in + the elements being tested directly. + +:returns: True if all elements in the sequence meet the predicate condition, + otherwise False. + +:raises: + * ValueError - If the Queryable is closed() + + * TypeError - If predicate is not callable. + +""" + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment5(self): + source_lines = [u'An empty Queryable.', + u'', + u'Note: The same empty instance will be returned each time.', + u'', + u'Returns: A Queryable over an empty sequence.', + u''] + + expected = """An empty Queryable. + +.. note:: + + The same empty instance will be returned each time. + +:returns: A Queryable over an empty sequence. + +""" + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment6(self): + source_lines = [u'A convenience factory for creating Records.', + u'', + u'Args:', + u' **kwargs: Each keyword argument will be used to initialise an', + u' attribute with the same name as the argument and the given', + u' value.', + u'', + u'Returns:', + u' A Record which has a named attribute for each of the keyword arguments.', + u''] + + expected = """A convenience factory for creating Records. + +:param \*\*kwargs: Each keyword argument will be used to initialise an + attribute with the same name as the argument and the given + value. + +:returns: A Record which has a named attribute for each of the keyword arguments. + +""" + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment7(self): + source = """Projects each element of a sequence to an intermediate new sequence, + flattens the resulting sequences into one sequence and optionally + transforms the flattened sequence using a selector function. + + Note: This method uses deferred execution. + + Args: + collection_selector: A unary function mapping each element of the + source iterable into an intermediate sequence. The single + argument of the collection_selector is the value of an element + from the source sequence. The return value should be an + iterable derived from that element value. The default + collection_selector, which is the identity function, assumes + that each element of the source sequence is itself iterable. + + result_selector: An optional unary function mapping the elements in + the flattened intermediate sequence to corresponding elements + of the result sequence. The single argument of the + result_selector is the value of an element from the flattened + intermediate sequence. The return value should be the + corresponding value in the result sequence. The default + result_selector is the identity function. + + Returns: + A Queryable over a generated sequence whose elements are the result + of applying the one-to-many collection_selector to each element of + the source sequence, concatenating the results into an intermediate + sequence, and then mapping each of those elements through the + result_selector into the result sequence. + + Raises: + ValueError: If this Queryable has been closed. + TypeError: If either collection_selector or result_selector are not + callable. + """ + + expected = """ Projects each element of a sequence to an intermediate new sequence, + flattens the resulting sequences into one sequence and optionally + transforms the flattened sequence using a selector function. + + .. note:: + + This method uses deferred execution. + + :param collection_selector: A unary function mapping each element of the + source iterable into an intermediate sequence. The single + argument of the collection_selector is the value of an element + from the source sequence. The return value should be an + iterable derived from that element value. The default + collection_selector, which is the identity function, assumes + that each element of the source sequence is itself iterable. + + :param result_selector: An optional unary function mapping the elements in + the flattened intermediate sequence to corresponding elements + of the result sequence. The single argument of the + result_selector is the value of an element from the flattened + intermediate sequence. The return value should be the + corresponding value in the result sequence. The default + result_selector is the identity function. + + :returns: A Queryable over a generated sequence whose elements are the result + of applying the one-to-many collection_selector to each element of + the source sequence, concatenating the results into an intermediate + sequence, and then mapping each of those elements through the + result_selector into the result sequence. + + :raises: + * ValueError - If this Queryable has been closed. + + * TypeError - If either collection_selector or result_selector are not + callable. + """ + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment8(self): + source = """A convenience factory for creating Records. + + Args: + **kwargs: Each keyword argument will be used to initialise an + attribute with the same name as the argument and the given + value. + + Returns: + A Record which has a named attribute for each of the keyword arguments. + """ + + expected = """A convenience factory for creating Records. + + :param \*\*kwargs: Each keyword argument will be used to initialise an + attribute with the same name as the argument and the given + value. + + :returns: A Record which has a named attribute for each of the keyword arguments. + +""" + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment9(self): + source_lines = [u'Parse a single line of a tree to determine depth and node.', + u'', + u'Args:', + u' This line is missing an argument name.', + u' ', + u'Returns:', + u' A 2-tuple containing the tree 0 based tree depth as the first', + u' element and the node description as the second element.', + u'', + u'Raises:', + u' ValueError: If line does not have the expected form.', + u''] + + self.assertRaises(HieroglyphError, lambda: parse_hieroglyph_text(source_lines)) + + def test_comment10(self): + source = """ + Execute the command described by concatenating the string function arguments + with the p4 -s global scripting flag and return the results in a dictionary. + + For example, to run the command:: + + p4 -s fstat -T depotFile foo.h + + call:: + + p4('fstat', '-T', 'depotFile', 'foo.h') + + Args: + args: The arguments to the p4 command as a list of objects which will + be converted to strings. + + Returns: + A dictionary of lists where each key in the dictionary is the field name + from the command output, and each value is a list of output lines in + order. + + Raises: + PerforceError: If the command could not be run or if the command + reported an error. + """ + + expected = """ + Execute the command described by concatenating the string function arguments + with the p4 -s global scripting flag and return the results in a dictionary. + + For example, to run the command:: + + p4 -s fstat -T depotFile foo.h + + call:: + + p4('fstat', '-T', 'depotFile', 'foo.h') + + :param args: The arguments to the p4 command as a list of objects which will + be converted to strings. + + :returns: A dictionary of lists where each key in the dictionary is the field name + from the command output, and each value is a list of output lines in + order. + + :raises: + PerforceError - If the command could not be run or if the command + reported an error. + +""" + + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment11(self): + source = """Projects each element of a sequence to an intermediate new sequence, + flattens the resulting sequences into one sequence and optionally + transforms the flattened sequence using a selector function. + + Warning: This method may explode at short notice. + + Args: + collection_selector: A unary function mapping each element of the + source iterable into an intermediate sequence. The single + argument of the collection_selector is the value of an element + from the source sequence. The return value should be an + iterable derived from that element value. The default + collection_selector, which is the identity function, assumes + that each element of the source sequence is itself iterable. + + result_selector: An optional unary function mapping the elements in + the flattened intermediate sequence to corresponding elements + of the result sequence. The single argument of the + result_selector is the value of an element from the flattened + intermediate sequence. The return value should be the + corresponding value in the result sequence. The default + result_selector is the identity function. + + Returns: + A Queryable over a generated sequence whose elements are the result + of applying the one-to-many collection_selector to each element of + the source sequence, concatenating the results into an intermediate + sequence, and then mapping each of those elements through the + result_selector into the result sequence. + + Raises: + ValueError: If this Queryable has been closed. + TypeError: If either collection_selector or result_selector are not + callable. + """ + + expected = """ Projects each element of a sequence to an intermediate new sequence, + flattens the resulting sequences into one sequence and optionally + transforms the flattened sequence using a selector function. + + .. warning:: + + This method may explode at short notice. + + :param collection_selector: A unary function mapping each element of the + source iterable into an intermediate sequence. The single + argument of the collection_selector is the value of an element + from the source sequence. The return value should be an + iterable derived from that element value. The default + collection_selector, which is the identity function, assumes + that each element of the source sequence is itself iterable. + + :param result_selector: An optional unary function mapping the elements in + the flattened intermediate sequence to corresponding elements + of the result sequence. The single argument of the + result_selector is the value of an element from the flattened + intermediate sequence. The return value should be the + corresponding value in the result sequence. The default + result_selector is the identity function. + + :returns: A Queryable over a generated sequence whose elements are the result + of applying the one-to-many collection_selector to each element of + the source sequence, concatenating the results into an intermediate + sequence, and then mapping each of those elements through the + result_selector into the result sequence. + + :raises: + * ValueError - If this Queryable has been closed. + + * TypeError - If either collection_selector or result_selector are not + callable. + """ + source_lines = source.splitlines() + actual_lines = parse_hieroglyph_text(source_lines) + expected_lines = expected.splitlines() + self.assertEqual(len(actual_lines), len(expected_lines)) + for actual_line, result_line in zip(actual_lines, expected_lines): + if len(actual_line.strip()) == 0: + self.assertTrue(len(result_line.strip()) == 0) + else: + self.assertEqual(actual_line, result_line) + + def test_comment12(self): + source = """Determine if all elements in the source sequence satisfy a condition. + + All of the source sequence will be consumed. + + Note: This method uses immediate execution. + + Args: + predicate: An optional single argument function used to test each + elements. If omitted, the bool() function is used resulting in + the elements being tested directly. + + Returns: + True if all elements in the sequence meet the predicate condition, + otherwise False. + + Raises: + This is not a proper exception description + """ + + source_lines = source.splitlines() + self.assertRaises(HieroglyphError, lambda: parse_hieroglyph_text(source_lines)) + diff --git a/docs/sphinx/hieroglyph/test/test_hierglyph.py b/docs/sphinx/hieroglyph/test/test_hierglyph.py new file mode 100644 index 000000000..42947cb0c --- /dev/null +++ b/docs/sphinx/hieroglyph/test/test_hierglyph.py @@ -0,0 +1,264 @@ +import unittest
+from hieroglyph.hieroglyph import first_paragraph_indent, gather_lines, unindent
+
+__author__ = 'Robert Smallshire'
+
+class UnindentTests(unittest.TestCase):
+
+ def test_zero_lines(self):
+ source = []
+ expected = []
+ actual = unindent(source)
+ self.assertEqual(actual, expected)
+
+ def test_one_zero_indent_line(self):
+ source = ["First line"]
+ expected = [(0, "First line")]
+ actual = unindent(source)
+ self.assertEqual(actual, expected)
+
+ def test_two_zero_indent_lines(self):
+ source = ["First line",
+ "Second line"]
+ expected = [(0, "First line"),
+ (0, "Second line")]
+ actual = unindent(source)
+ self.assertEqual(actual, expected)
+
+ def test_two_indented_lines(self):
+ source = [" First line",
+ " Second line"]
+ expected = [(4, "First line"),
+ (6, "Second line")]
+ actual = unindent(source)
+ self.assertEqual(actual, expected)
+
+ def test_whitespace_line(self):
+ source = [" "]
+ expected = [(4, "")]
+ actual = unindent(source)
+ self.assertEqual(actual, expected)
+
+ def test_tab_line(self):
+ source = ["\tHello"]
+ expected = [(1, "Hello")]
+ actual = unindent(source)
+ self.assertEqual(actual, expected)
+
+
+class FirstParagraphIndentTests(unittest.TestCase):
+
+ def test_zero_lines(self):
+ source = []
+ expected = []
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_single_line_non_indented_comment(self):
+ source = [(0, "A single line comment")]
+ expected = [(0, "A single line comment")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_single_line_indented_comment(self):
+ source = [(4, "A single line comment")]
+ expected = [(4, "A single line comment")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_double_line_non_indented_comment(self):
+ source = [(0, "The first line"),
+ (0, "The second line")]
+ expected = [(0, "The first line"),
+ (0, "The second line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_double_line_indented_comment(self):
+ source = [(4, "The first line"),
+ (4, "The second line")]
+ expected = [(4, "The first line"),
+ (4, "The second line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_first_line_indent(self):
+ source = [(4, "The first line"),
+ (0, "The second line")]
+ expected = [(4, "The first line"),
+ (0, "The second line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_first_line_non_indent(self):
+ source = [(0, "The first line"),
+ (4, "The second line")]
+ expected = [(4, "The first line"),
+ (4, "The second line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_increasing_indent(self):
+ source = [(0, "The first line"),
+ (4, "The second line"),
+ (8, "The third line")]
+ expected = [(4, "The first line"),
+ (4, "The second line"),
+ (8, "The third line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_separate_paragraphs(self):
+ source = [(0, "This is the first paragraph"),
+ (0, ""),
+ (4, "This is the second paragraph")]
+ expected = [(0, "This is the first paragraph"),
+ (0, ""),
+ (4, "This is the second paragraph")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_separate_paragraphs_indented(self):
+ source = [(4, "This is the first paragraph"),
+ (4, ""),
+ (8, "This is the second paragraph")]
+ expected = [(4, "This is the first paragraph"),
+ (4, ""),
+ (8, "This is the second paragraph")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_separated_lines_first_line_non_indented(self):
+ source = [(0, "The first line"),
+ (0, ""),
+ (4, "The third line")]
+ expected = [(0, "The first line"),
+ (0, ""),
+ (4, "The third line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+ def test_separated_lines_first_line_indented(self):
+ source = [(4, "The first line"),
+ (4, ""),
+ (4, "The third line")]
+ expected = [(4, "The first line"),
+ (4, ""),
+ (4, "The third line")]
+ actual = first_paragraph_indent(source)
+ self.assertEqual(actual, expected)
+
+class GatherLinesTests(unittest.TestCase):
+
+ def test_empty(self):
+ source = []
+ expected = []
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_one_liner(self):
+ source = [(0, 'One liner')]
+ expected = [(0, ['One liner'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_two_liner(self):
+ source = [(0, 'First line'),
+ (0, 'Second line')]
+ expected = [(0, ['First line',
+ 'Second line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_separated_lines(self):
+ source = [(0, 'First line'),
+ (0, ''),
+ (0, 'Third line')]
+ expected = [(0, ['First line',
+ '']),
+ (0, ['Third line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_separated_multi_lines(self):
+ source = [(0, 'First line'),
+ (0, 'Second line'),
+ (0, ''),
+ (0, 'Fourth line'),
+ (0, 'Fifth line')]
+ expected = [(0, ['First line',
+ 'Second line',
+ '']),
+ (0, ['Fourth line',
+ 'Fifth line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+
+ def test_indented_lines(self):
+ source = [(0, 'First line'),
+ (4, 'Second line')]
+ expected = [(0, ['First line']),
+ (4, ['Second line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_dedented_lines(self):
+ source = [(4, 'First line'),
+ (0, 'Second line')]
+ expected = [(4, ['First line']),
+ (0, ['Second line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_indented_multi_lines(self):
+ source = [(0, 'First line'),
+ (0, 'Second line'),
+ (4, 'Third line'),
+ (4, 'Fourth line')]
+ expected = [(0, ['First line',
+ 'Second line']),
+ (4, ['Third line',
+ 'Fourth line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_dedented_multi_lines(self):
+ source = [(4, 'First line'),
+ (4, 'Second line'),
+ (0, 'Third line'),
+ (0, 'Fourth line')]
+ expected = [(4, ['First line',
+ 'Second line']),
+ (0, ['Third line',
+ 'Fourth line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_indented_separated_multi_lines(self):
+ source = [(0, 'First line'),
+ (0, 'Second line'),
+ (0, ''),
+ (4, 'Fourth line'),
+ (4, 'Fifth line')]
+ expected = [(0, ['First line',
+ 'Second line',
+ '']),
+ (4, ['Fourth line',
+ 'Fifth line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
+
+ def test_dedented_separated_multi_lines(self):
+ source = [(4, 'First line'),
+ (4, 'Second line'),
+ (4, ''),
+ (0, 'Fourth line'),
+ (0, 'Fifth line')]
+ expected = [(4, ['First line',
+ 'Second line',
+ '']),
+ (0, ['Fourth line',
+ 'Fifth line'])]
+ actual = gather_lines(source)
+ self.assertEqual(actual, expected)
diff --git a/docs/sphinx/hieroglyph/test/test_nodes.py b/docs/sphinx/hieroglyph/test/test_nodes.py new file mode 100644 index 000000000..4cc17b477 --- /dev/null +++ b/docs/sphinx/hieroglyph/test/test_nodes.py @@ -0,0 +1,386 @@ +import unittest
+from hieroglyph.nodes import Node, Arg, Raises, Except, Returns, Warning, Note
+
+__author__ = 'Robert Smallshire'
+
+class NodeTests(unittest.TestCase):
+
+ def test_create_default_node(self):
+ node = Node()
+ self.assertEqual(node.indent, 0)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_create_with_indent(self):
+ node = Node(indent=4)
+ self.assertEqual(node.indent, 4)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_create_with_lines(self):
+ node = Node(lines= ['First', 'Second', 'Third'])
+ self.assertEqual(node.indent, 0)
+ self.assertEqual(node.lines, ['First', 'Second', 'Third'])
+ self.assertIsNone(node.parent)
+
+ def test_repr(self):
+ node = Node(5, ['One', 'Two', 'Three'])
+ actual = repr(node)
+ expected = "Node(5, ['One', 'Two', 'Three'], children=[])"
+ self.assertEqual(expected, actual)
+
+ def test_add_one_child(self):
+ node = Node()
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Node()
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_render_rst_empty(self):
+ node = Node()
+ rst = node.render_rst()
+ self.assertEqual(len(rst), 0)
+
+ def test_render_rst_indent(self):
+ node = Node(indent=4)
+ rst = node.render_rst()
+ self.assertEqual(len(rst), 0)
+
+ def test_render_rst_lines(self):
+ node = Node(lines= ['First',
+ 'Second',
+ 'Third'])
+ rst = node.render_rst()
+ self.assertEqual(rst, ['First',
+ 'Second',
+ 'Third'])
+
+ def test_render_rst_indented_lines(self):
+ node = Node(indent=3, lines= ['First',
+ 'Second',
+ 'Third'])
+ rst = node.render_rst()
+ self.assertEqual(rst, [' First',
+ ' Second',
+ ' Third'])
+
+ def test_render_rst_with_child(self):
+ node = Node(indent=4, lines=["Parent"])
+ child = Node(indent=8, lines=["Child"], parent=node)
+ node.add_child(child)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' Parent',
+ ' Child'])
+
+ def test_render_rst_with_children(self):
+ node = Node(indent=4, lines=["Parent"])
+ child_a = Node(indent=8, lines=["ChildA"], parent=node)
+ node.add_child(child_a)
+ child_b = Node(indent=6, lines=["ChildB"], parent=node)
+ node.add_child(child_b)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' Parent',
+ ' ChildA',
+ ' ChildB'])
+
+
+class ArgTests(unittest.TestCase):
+
+ def test_create(self):
+ node = Arg(5, 10, 'foo')
+ self.assertEqual(node.indent, 5)
+ self.assertEqual(node.child_indent, 10)
+ self.assertEqual(node.name, 'foo')
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_set_type(self):
+ node = Arg(5, 10, 'foo')
+ node.type = 'str'
+ self.assertEqual(node.type, 'str')
+
+ def test_add_one_child(self):
+ node = Arg(5, 10, 'foo')
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Arg(5, 10, 'foo')
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_repr(self):
+ node = Arg(5, 10, 'foo')
+ actual = repr(node)
+ expected = "Arg('foo', None, children=[])"
+ self.assertEqual(expected, actual)
+
+ def test_render_rst_empty(self):
+ node = Arg(5, 10, 'bar')
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :param bar: ',
+ ''])
+
+ def test_render_rst_with_child(self):
+ node = Arg(5, 10, 'bar')
+ child = Node(indent=10, lines=["Description"], parent=node)
+ node.add_child(child)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :param bar: Description',
+ ''])
+
+ def test_render_rst_with_children(self):
+ node = Arg(5, 10, 'bar')
+ child_a = Node(indent=10, lines=["ChildA"], parent=node)
+ node.add_child(child_a)
+ child_b = Node(indent=10, lines=["ChildB"], parent=node)
+ node.add_child(child_b)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :param bar: ChildA',
+ ' ChildB',
+ ''])
+
+ def test_render_rst_with_type(self):
+ node = Arg(5, 10, 'bar')
+ node.type = 'str'
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :param bar: ',
+ ' :type bar: str',
+ ''])
+
+
+class RaisesTests(unittest.TestCase):
+
+ def test_create_default_node(self):
+ node = Raises()
+ self.assertEqual(node.indent, 0)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_create_with_indent(self):
+ node = Raises(indent=4)
+ self.assertEqual(node.indent, 4)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_repr(self):
+ node = Raises(5)
+ actual = repr(node)
+ expected = "Raises(5, children=[])"
+ self.assertEqual(expected, actual)
+
+ def test_add_one_child(self):
+ node = Raises()
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Raises()
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_render_rst_empty(self):
+ node = Raises()
+ rst = node.render_rst()
+ self.assertEqual(rst, [':raises:',
+ ''])
+
+ def test_render_rst_indent(self):
+ node = Raises(indent=5)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :raises:',
+ ''])
+
+ def test_render_rst_with_child(self):
+ node = Raises(5)
+ child = Node(indent=10, lines=["Description"], parent=node)
+ node.add_child(child)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :raises:',
+ ' Description',
+ ''])
+
+ def test_render_rst_with_children(self):
+ node = Raises(5)
+ child_a = Node(indent=10, lines=["ChildA"], parent=node)
+ node.add_child(child_a)
+ child_b = Node(indent=10, lines=["ChildB"], parent=node)
+ node.add_child(child_b)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' :raises:',
+ ' ChildA',
+ ' ChildB',
+ ''])
+
+
+class ExceptTests(unittest.TestCase):
+
+ def test_create(self):
+ node = Except(5, 'FooError')
+ self.assertEqual(node.indent, 5)
+ self.assertEqual(node.type, 'FooError')
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_add_one_child(self):
+ node = Except(5, 'FooError')
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Except(5, 'FooError')
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_repr(self):
+ node = Except(5,'FooError')
+ actual = repr(node)
+ expected = "Except('FooError', children=[])"
+ self.assertEqual(expected, actual)
+
+ def test_render_rst_empty(self):
+ node = Except(5, 'FooError')
+ rst = node.render_rst()
+ self.assertEqual(rst, [' * FooError - ',
+ ''])
+
+ def test_render_rst_indent(self):
+ node = Except(5, 'FooError')
+ rst = node.render_rst()
+ self.assertEqual(rst, [' * FooError - ',
+ ''])
+
+ def test_render_rst_with_child(self):
+ node = Except(5, 'FooError')
+ child = Node(indent=10, lines=["Description"], parent=node)
+ node.add_child(child)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' * FooError - Description',
+ ''])
+
+ def test_render_rst_with_children(self):
+ node = Except(5, 'FooError')
+ child_a = Node(indent=10, lines=["ChildA"], parent=node)
+ node.add_child(child_a)
+ child_b = Node(indent=10, lines=["ChildB"], parent=node)
+ node.add_child(child_b)
+ rst = node.render_rst()
+ self.assertEqual(rst, [' * FooError - ChildA',
+ ' ChildB',
+ ''])
+
+class ReturnsTests(unittest.TestCase):
+
+ def test_create(self):
+ node = Returns(5)
+ self.assertEqual(node.indent, 5)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_add_one_child(self):
+ node = Returns(5)
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Returns(5)
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_repr(self):
+ node = Returns(5)
+ actual = repr(node)
+ expected = "Returns(5, children=[])"
+ self.assertEqual(expected, actual)
+
+ # TODO test_render_rst
+
+class WarningTests(unittest.TestCase):
+
+ def test_create(self):
+ node = Warning(5)
+ self.assertEqual(node.indent, 5)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_add_one_child(self):
+ node = Warning(5)
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Warning(5)
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_repr(self):
+ node = Warning(5)
+ actual = repr(node)
+ expected = "Warning(5, children=[])"
+ self.assertEqual(expected, actual)
+
+ # TODO test_render_rst
+
+class NoteTests(unittest.TestCase):
+
+ def test_create(self):
+ node = Note(5)
+ self.assertEqual(node.indent, 5)
+ self.assertEqual(node.lines, [])
+ self.assertIsNone(node.parent)
+
+ def test_add_one_child(self):
+ node = Note(5)
+ child = Node(parent=node)
+ node.add_child(child)
+ self.assertIs(node.children[0], child)
+
+ def test_add_two_children(self):
+ node = Note(5)
+ child0 = Node(parent=node)
+ child1 = Node(parent=node)
+ node.add_child(child0)
+ node.add_child(child1)
+ self.assertIs(node.children[0], child0)
+ self.assertIs(node.children[1], child1)
+
+ def test_repr(self):
+ node = Note(5)
+ actual = repr(node)
+ expected = "Note(5, children=[])"
+ self.assertEqual(expected, actual)
+
+ # TODO test_render_rst
diff --git a/docs/sphinx/hieroglyph/version.py b/docs/sphinx/hieroglyph/version.py new file mode 100644 index 000000000..d060125c0 --- /dev/null +++ b/docs/sphinx/hieroglyph/version.py @@ -0,0 +1,3 @@ +'''Specification of the hieroglyph version'''
+
+__version__ = '0.6'
diff --git a/docs/sphinx/run_sphinx_build.sh.in b/docs/sphinx/run_sphinx_build.sh.in new file mode 100644 index 000000000..bc89f2de7 --- /dev/null +++ b/docs/sphinx/run_sphinx_build.sh.in @@ -0,0 +1,7 @@ +#!/bin/bash + +echo "Creating Sphinx documentation in: @CMAKE_CURRENT_BINARY_DIR@/sphinx_out" + +LD_LIBRARY_PATH="@CMAKE_INSTALL_PREFIX@/lib" +@SPHINX_EXECUTABLE@ -b html -c @CMAKE_CURRENT_BINARY_DIR@/ @CMAKE_CURRENT_SOURCE_DIR@/source @CMAKE_CURRENT_BINARY_DIR@/sphinx_out + diff --git a/docs/sphinx/source/atsc/blks.rst b/docs/sphinx/source/atsc/blks.rst new file mode 100644 index 000000000..6f51a2287 --- /dev/null +++ b/docs/sphinx/source/atsc/blks.rst @@ -0,0 +1,20 @@ +gnuradio.atsc: Signal Processing Blocks +======================================= + +.. 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/atsc/index.rst b/docs/sphinx/source/atsc/index.rst new file mode 100644 index 000000000..2371f2456 --- /dev/null +++ b/docs/sphinx/source/atsc/index.rst @@ -0,0 +1,62 @@ +gnuradio.atsc +============= + +.. automodule:: gnuradio.atsc + +Signal Processing Blocks +------------------------ + +.. autosummary:: + :nosignatures: + + gnuradio.atsc.bit_timing_loop + gnuradio.atsc.deinterleaver + gnuradio.atsc.depad + gnuradio.atsc.derandomizer + gnuradio.atsc.ds_to_softds + gnuradio.atsc.equalizer + gnuradio.atsc.field_sync_demux + gnuradio.atsc.field_sync_mux + gnuradio.atsc.fpll + gnuradio.atsc.fs_checker + gnuradio.atsc.interleaver + gnuradio.atsc.pad + gnuradio.atsc.randomizer + gnuradio.atsc.rs_decoder + gnuradio.atsc.rs_encoder + gnuradio.atsc.trellis_encoder + gnuradio.atsc.viterbi_decoder + +Constants +--------- + +.. autosummary:: + :nosignatures: + + gnuradio.atsc.ATSC_DATA_SEGMENT_LENGTH + gnuradio.atsc.ATSC_DATA_SEGMENT_RATE + gnuradio.atsc.ATSC_DSEGS_PER_FIELD + gnuradio.atsc.ATSC_MPEG_DATA_LENGTH + gnuradio.atsc.ATSC_MPEG_PKT_LENGTH + gnuradio.atsc.ATSC_MPEG_RS_ENCODED_LENGTH + gnuradio.atsc.ATSC_SYMBOL_RATE + gnuradio.atsc.MPEG_SYNC_BYTE + gnuradio.atsc.MPEG_TRANSPORT_ERROR_BIT + +Sizes +--------- + +.. autosummary:: + :nosignatures: + + gnuradio.atsc.sizeof_atsc_data_segment + gnuradio.atsc.sizeof_atsc_data_segment_pad + gnuradio.atsc.sizeof_atsc_mpeg_packet + gnuradio.atsc.sizeof_atsc_mpeg_packet_no_sync + gnuradio.atsc.sizeof_atsc_mpeg_packet_no_sync_pad + gnuradio.atsc.sizeof_atsc_mpeg_packet_pad + gnuradio.atsc.sizeof_atsc_mpeg_packet_rs_encoded + gnuradio.atsc.sizeof_atsc_mpeg_packet_rs_encoded_pad + gnuradio.atsc.sizeof_atsc_soft_data_segment + gnuradio.atsc.sizeof_atsc_soft_data_segment_pad + diff --git a/docs/sphinx/source/audio/index.rst b/docs/sphinx/source/audio/index.rst new file mode 100644 index 000000000..d0bc4f3c0 --- /dev/null +++ b/docs/sphinx/source/audio/index.rst @@ -0,0 +1,7 @@ +gnuradio.audio +============== + +.. automodule:: gnuradio.audio + +.. autooldblock:: gnuradio.audio.source +.. autooldblock:: gnuradio.audio.sink diff --git a/docs/sphinx/source/blks2/blks.rst b/docs/sphinx/source/blks2/blks.rst new file mode 100644 index 000000000..c28c7af0f --- /dev/null +++ b/docs/sphinx/source/blks2/blks.rst @@ -0,0 +1,31 @@ +gnuradio.blks2: Signal Processing Blocks +======================================== + +.. autopyblock:: gnuradio.blks2.am_demod_cf +.. autopyblock:: gnuradio.blks2.ctcss_gen_f +.. autopyblock:: gnuradio.blks2.demod_10k0a3e_cf +.. autopyblock:: gnuradio.blks2.demod_200kf3e_cf +.. autopyblock:: gnuradio.blks2.demod_20k0f3e_cf +.. autopyblock:: gnuradio.blks2.fm_demod_cf +.. autopyblock:: gnuradio.blks2.logpwrfft_c +.. autopyblock:: gnuradio.blks2.logpwrfft_f +.. autopyblock:: gnuradio.blks2.pfb_arb_resampler_ccf +.. autopyblock:: gnuradio.blks2.pfb_arb_resampler_fff +.. autopyblock:: gnuradio.blks2.pfb_channelizer_ccf +.. autopyblock:: gnuradio.blks2.pfb_decimator_ccf +.. autopyblock:: gnuradio.blks2.pfb_interpolator_ccf +.. autopyblock:: gnuradio.blks2.rational_resampler_ccc +.. autopyblock:: gnuradio.blks2.rational_resampler_ccf +.. autopyblock:: gnuradio.blks2.rational_resampler_fff +.. autopyblock:: gnuradio.blks2.analysis_filterbank +.. autopyblock:: gnuradio.blks2.fm_deemph +.. autopyblock:: gnuradio.blks2.fm_preemph +.. autopyblock:: gnuradio.blks2.nbfm_rx +.. autopyblock:: gnuradio.blks2.nbfm_tx +.. autopyblock:: gnuradio.blks2.stream_to_vector_decimator +.. autopyblock:: gnuradio.blks2.standard_squelch +.. autopyblock:: gnuradio.blks2.synthesis_filterbank +.. autopyblock:: gnuradio.blks2.wfm_rcv +.. autopyblock:: gnuradio.blks2.wfm_rcv_fmdet +.. autopyblock:: gnuradio.blks2.wfm_rcv_pll +.. autopyblock:: gnuradio.blks2.wfm_tx diff --git a/docs/sphinx/source/blks2/index.rst b/docs/sphinx/source/blks2/index.rst new file mode 100644 index 000000000..4df8e5a79 --- /dev/null +++ b/docs/sphinx/source/blks2/index.rst @@ -0,0 +1,47 @@ +gnuradio.blks2 +============== + +.. automodule:: gnuradio.blks2 + +Signal Processing Blocks +------------------------ + +.. autosummary:: + :nosignatures: + + gnuradio.blks2.am_demod_cf + gnuradio.blks2.ctcss_gen_f + gnuradio.blks2.demod_10k0a3e_cf + gnuradio.blks2.demod_200kf3e_cf + gnuradio.blks2.demod_20k0f3e_cf + gnuradio.blks2.fm_demod_cf + gnuradio.blks2.logpwrfft_c + gnuradio.blks2.logpwrfft_f + gnuradio.blks2.pfb_arb_resampler_ccf + gnuradio.blks2.pfb_arb_resampler_fff + gnuradio.blks2.pfb_channelizer_ccf + gnuradio.blks2.pfb_decimator_ccf + gnuradio.blks2.pfb_interpolator_ccf + gnuradio.blks2.rational_resampler_ccc + gnuradio.blks2.rational_resampler_ccf + gnuradio.blks2.rational_resampler_fff + gnuradio.blks2.analysis_filterbank + gnuradio.blks2.fm_deemph + gnuradio.blks2.fm_preemph + gnuradio.blks2.nbfm_rx + gnuradio.blks2.nbfm_tx + gnuradio.blks2.stream_to_vector_decimator + gnuradio.blks2.standard_squelch + gnuradio.blks2.synthesis_filterbank + gnuradio.blks2.wfm_rcv + gnuradio.blks2.wfm_rcv_fmdet + gnuradio.blks2.wfm_rcv_pll + gnuradio.blks2.wfm_tx + +Utility Functions +----------------- + +.. autosummary:: + :nosignatures: + + gnuradio.blks2.design_filter diff --git a/docs/sphinx/source/blks2/utilities.rst b/docs/sphinx/source/blks2/utilities.rst new file mode 100644 index 000000000..3ce068fb4 --- /dev/null +++ b/docs/sphinx/source/blks2/utilities.rst @@ -0,0 +1,4 @@ +gnuradio.blks2: Utility Functions +================================= + +.. autoclass:: gnuradio.blks2.design_filter diff --git a/docs/sphinx/source/conf.py.in b/docs/sphinx/source/conf.py.in new file mode 100644 index 000000000..aa7b122cc --- /dev/null +++ b/docs/sphinx/source/conf.py.in @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- +# +# GNU Radio documentation build configuration file, created by +# sphinx-quickstart on Sun Oct 16 22:27:51 2011. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('@CMAKE_CURRENT_SOURCE_DIR@')) +sys.path.insert(0, '@CMAKE_INSTALL_PREFIX@/@GR_PYTHON_DIR@') + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.autosummary', 'sphinx.ext.mathjax', 'gnuradio_sphinx', 'hieroglyph'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'GNU Radio' +copyright = u'2012, Free Software Foundation' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '@VERSION@' +# The full version, including alpha/beta/rc tags. +release = '@VERSION@' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'GNURadiodoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'GNURadio.tex', u'GNU Radio Documentation', + u'Free Software Foundation', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'gnuradio', u'GNU Radio Documentation', + [u'Free Software Foundation'], 1) +] diff --git a/docs/sphinx/source/digital/blocks.rst b/docs/sphinx/source/digital/blocks.rst new file mode 100644 index 000000000..68ec8dad1 --- /dev/null +++ b/docs/sphinx/source/digital/blocks.rst @@ -0,0 +1,51 @@ +gnuradio.digital: Signal Processing Blocks +========================================== + +.. 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 +.. autopyblock:: gnuradio.digital.bpsk.dbpsk_mod +.. autopyblock:: gnuradio.digital.qpsk.dqpsk_demod +.. autopyblock:: gnuradio.digital.qpsk.dqpsk_mod +.. autopyblock:: gnuradio.digital.gmsk.gmsk_demod +.. autopyblock:: gnuradio.digital.gmsk.gmsk_mod +.. autopyblock:: gnuradio.digital.bpsk.bpsk_demod +.. autopyblock:: gnuradio.digital.bpsk.bpsk_mod +.. autopyblock:: gnuradio.digital.psk.psk_demod +.. autopyblock:: gnuradio.digital.psk.psk_mod +.. autopyblock:: gnuradio.digital.qam.qam_demod +.. autopyblock:: gnuradio.digital.qam.qam_mod +.. autopyblock:: gnuradio.digital.qpsk.qpsk_demod +.. autopyblock:: gnuradio.digital.qpsk.qpsk_mod +.. autopyblock:: gnuradio.digital.cpm.cpm_mod +.. autopyblock:: gnuradio.digital.pkt.mod_pkts +.. autopyblock:: gnuradio.digital.pkt.demod_pkts +.. autopyblock:: gnuradio.digital.ofdm_cyclic_prefixer +.. autopyblock:: gnuradio.digital.ofdm_frame_acquisition +.. autopyblock:: gnuradio.digital.ofdm_frame_sink +.. autopyblock:: gnuradio.digital.ofdm_insert_preamble +.. autopyblock:: gnuradio.digital.ofdm_mapper_bcv +.. autopyblock:: gnuradio.digital.ofdm_mod +.. autopyblock:: gnuradio.digital.ofdm_demod +.. autopyblock:: gnuradio.digital.ofdm_receiver +.. autopyblock:: gnuradio.digital.ofdm_sampler +.. autopyblock:: gnuradio.digital.ofdm_sync_fixed +.. autopyblock:: gnuradio.digital.ofdm_sync_ml +.. autopyblock:: gnuradio.digital.ofdm_sync_pn +.. autopyblock:: gnuradio.digital.ofdm_sync_pnac diff --git a/docs/sphinx/source/digital/constellations.rst b/docs/sphinx/source/digital/constellations.rst new file mode 100644 index 000000000..3fa02613a --- /dev/null +++ b/docs/sphinx/source/digital/constellations.rst @@ -0,0 +1,13 @@ +gnuradio.digital: Constellations +================================ + +.. autofunction:: gnuradio.digital.constellation_8psk +.. autofunction:: gnuradio.digital.constellation_bpsk +.. autofunction:: gnuradio.digital.constellation_calcdist +.. autofunction:: gnuradio.digital.constellation_dqpsk +.. autofunction:: gnuradio.digital.constellation_psk +.. autofunction:: gnuradio.digital.constellation_qpsk +.. autofunction:: gnuradio.digital.constellation_rect +.. autofunction:: gnuradio.digital.qpsk.qpsk_constellation +.. autofunction:: gnuradio.digital.psk.psk_constellation +.. autofunction:: gnuradio.digital.qam.qam_constellation diff --git a/docs/sphinx/source/digital/index.rst b/docs/sphinx/source/digital/index.rst new file mode 100644 index 000000000..da5227e45 --- /dev/null +++ b/docs/sphinx/source/digital/index.rst @@ -0,0 +1,133 @@ +gnuradio.digital +================ + +.. automodule:: gnuradio.digital + +Signal Processing Blocks +------------------------ + +.. autosummary:: + :nosignatures: + + gnuradio.digital.fll_band_edge_cc + gnuradio.digital.kurtotic_equalizer_cc + gnuradio.digital.lms_dd_equalizer_cc + gnuradio.digital.mpsk_receiver_cc + gnuradio.digital.mpsk_snr_est_cc + gnuradio.digital.clock_recovery_mm_cc + gnuradio.digital.clock_recovery_mm_ff + gnuradio.digital.constellation_decoder_cb + gnuradio.digital.constellation_receiver_cb + gnuradio.digital.correlate_access_code_bb + gnuradio.digital.costas_loop_cc + gnuradio.digital.cma_equalizer_cc + gnuradio.digital.binary_slicer_fb + gnuradio.digital.gmskmod_bc + gnuradio.digital.probe_mpsk_snr_est_c + gnuradio.digital.cpmmod_bc + gnuradio.digital.generic_demod + gnuradio.digital.generic_mod + gnuradio.digital.bpsk.dbpsk_demod + gnuradio.digital.bpsk.dbpsk_mod + gnuradio.digital.qpsk.dqpsk_demod + gnuradio.digital.qpsk.dqpsk_mod + gnuradio.digital.gmsk.gmsk_demod + gnuradio.digital.gmsk.gmsk_mod + gnuradio.digital.bpsk.bpsk_demod + gnuradio.digital.bpsk.bpsk_mod + gnuradio.digital.psk.psk_demod + gnuradio.digital.psk.psk_mod + gnuradio.digital.qam.qam_demod + gnuradio.digital.qam.qam_mod + gnuradio.digital.qpsk.qpsk_demod + gnuradio.digital.qpsk.qpsk_mod + gnuradio.digital.cpm.cpm_mod + gnuradio.digital.pkt.mod_pkts + gnuradio.digital.pkt.demod_pkts + gnuradio.digital.ofdm_cyclic_prefixer + gnuradio.digital.ofdm_frame_acquisition + gnuradio.digital.ofdm_frame_sink + gnuradio.digital.ofdm_insert_preamble + gnuradio.digital.ofdm_mapper_bcv + gnuradio.digital.ofdm_mod + gnuradio.digital.ofdm_demod + gnuradio.digital.ofdm_receiver + gnuradio.digital.ofdm_sampler + gnuradio.digital.ofdm_sync_fixed + gnuradio.digital.ofdm_sync_ml + gnuradio.digital.ofdm_sync_pn + gnuradio.digital.ofdm_sync_pnac + +Constellations +-------------- + +.. autosummary:: + :nosignatures: + + gnuradio.digital.constellation_8psk + gnuradio.digital.constellation_bpsk + gnuradio.digital.constellation_calcdist + gnuradio.digital.constellation_dqpsk + gnuradio.digital.constellation_psk + gnuradio.digital.constellation_qpsk + gnuradio.digital.constellation_qpsk + gnuradio.digital.constellation_rect + gnuradio.digital.qpsk.qpsk_constellation + gnuradio.digital.psk.psk_constellation + gnuradio.digital.qam.qam_constellation + +Modulation Utilties +------------------- + +.. autosummary:: + :nosignatures: + + gnuradio.digital.utils.gray_code.gray_code + gnuradio.digital.utils.mod_codes.GRAY_CODE + gnuradio.digital.utils.mod_codes.NO_CODE + gnuradio.digital.modulation_utils.add_type_1_constellation + gnuradio.digital.modulation_utils.add_type_1_demod + gnuradio.digital.modulation_utils.add_type_1_mod + gnuradio.digital.modulation_utils.type_1_constellations + gnuradio.digital.modulation_utils.type_1_demods + gnuradio.digital.modulation_utils.type_1_mods + +Packet Utilities +---------------- + +.. autosummary:: + :nosignatures: + + gnuradio.digital.packet_utils.conv_1_0_string_to_packed_binary_string + gnuradio.digital.packet_utils.conv_packed_binary_string_to_1_0_string + gnuradio.digital.packet_utils.default_access_code + gnuradio.digital.packet_utils.dewhiten + gnuradio.digital.packet_utils.is_1_0_string + gnuradio.digital.packet_utils.make_header + gnuradio.digital.packet_utils.make_packet + gnuradio.digital.packet_utils.preamble + gnuradio.digital.packet_utils.random_mask_tuple + gnuradio.digital.packet_utils.random_mask_vec8 + gnuradio.digital.packet_utils.string_to_hex_list + gnuradio.digital.packet_utils.unmake_packet + gnuradio.digital.packet_utils.whiten + gnuradio.digital.crc.check_crc32 + gnuradio.digital.crc.gen_and_append_crc32 + +OFDM Packet Utilities +--------------------- + +.. autosummary:: + :nosignatures: + + gnuradio.digital.ofdm_packet_utils.conv_1_0_string_to_packed_binary_string + gnuradio.digital.ofdm_packet_utils.conv_packed_binary_string_to_1_0_string + gnuradio.digital.ofdm_packet_utils.dewhiten + gnuradio.digital.ofdm_packet_utils.is_1_0_string + gnuradio.digital.ofdm_packet_utils.make_header + gnuradio.digital.ofdm_packet_utils.make_packet + gnuradio.digital.ofdm_packet_utils.random_mask_tuple + gnuradio.digital.ofdm_packet_utils.random_mask_vec8 + gnuradio.digital.ofdm_packet_utils.string_to_hex_list + gnuradio.digital.ofdm_packet_utils.unmake_packet + gnuradio.digital.ofdm_packet_utils.whiten diff --git a/docs/sphinx/source/digital/ofdm.rst b/docs/sphinx/source/digital/ofdm.rst new file mode 100644 index 000000000..8680503f2 --- /dev/null +++ b/docs/sphinx/source/digital/ofdm.rst @@ -0,0 +1,14 @@ +gnuradio.digital: OFDM Packet Utilities +======================================= + +.. autofunction:: gnuradio.digital.ofdm_packet_utils.conv_1_0_string_to_packed_binary_string +.. autofunction:: gnuradio.digital.ofdm_packet_utils.conv_packed_binary_string_to_1_0_string +.. autofunction:: gnuradio.digital.ofdm_packet_utils.dewhiten +.. autofunction:: gnuradio.digital.ofdm_packet_utils.is_1_0_string +.. autofunction:: gnuradio.digital.ofdm_packet_utils.make_header +.. autofunction:: gnuradio.digital.ofdm_packet_utils.make_packet +.. autofunction:: gnuradio.digital.ofdm_packet_utils.random_mask_tuple +.. autofunction:: gnuradio.digital.ofdm_packet_utils.random_mask_vec8 +.. autofunction:: gnuradio.digital.ofdm_packet_utils.string_to_hex_list +.. autofunction:: gnuradio.digital.ofdm_packet_utils.unmake_packet +.. autofunction:: gnuradio.digital.ofdm_packet_utils.whiten diff --git a/docs/sphinx/source/digital/pkt_utils.rst b/docs/sphinx/source/digital/pkt_utils.rst new file mode 100644 index 000000000..112e103a2 --- /dev/null +++ b/docs/sphinx/source/digital/pkt_utils.rst @@ -0,0 +1,18 @@ +gnuradio.digital: Packet Utilities +================================== + +.. autofunction:: gnuradio.digital.packet_utils.conv_1_0_string_to_packed_binary_string +.. autofunction:: gnuradio.digital.packet_utils.conv_packed_binary_string_to_1_0_string +.. data:: gnuradio.digital.packet_utils.default_access_code +.. autofunction:: gnuradio.digital.packet_utils.dewhiten +.. autofunction:: gnuradio.digital.packet_utils.is_1_0_string +.. autofunction:: gnuradio.digital.packet_utils.make_header +.. autofunction:: gnuradio.digital.packet_utils.make_packet +.. data:: gnuradio.digital.packet_utils.preamble +.. autofunction:: gnuradio.digital.packet_utils.random_mask_tuple +.. autofunction:: gnuradio.digital.packet_utils.random_mask_vec8 +.. autofunction:: gnuradio.digital.packet_utils.string_to_hex_list +.. autofunction:: gnuradio.digital.packet_utils.unmake_packet +.. autofunction:: gnuradio.digital.packet_utils.whiten +.. autofunction:: gnuradio.digital.crc.check_crc32 +.. autofunction:: gnuradio.digital.crc.gen_and_append_crc32 diff --git a/docs/sphinx/source/digital/utilities.rst b/docs/sphinx/source/digital/utilities.rst new file mode 100644 index 000000000..7a08725a5 --- /dev/null +++ b/docs/sphinx/source/digital/utilities.rst @@ -0,0 +1,12 @@ +gnuradio.digital: Modulation Utilities +====================================== + +.. autofunction:: gnuradio.digital.utils.gray_code.gray_code +.. data:: gnuradio.digital.utils.mod_codes.GRAY_CODE +.. data:: gnuradio.digital.utils.mod_codes.NO_CODE +.. autofunction:: gnuradio.digital.modulation_utils.add_type_1_constellation +.. autofunction:: gnuradio.digital.modulation_utils.add_type_1_demod +.. autofunction:: gnuradio.digital.modulation_utils.add_type_1_mod +.. data:: gnuradio.digital.modulation_utils.type_1_constellations +.. data:: gnuradio.digital.modulation_utils.type_1_demods +.. data:: gnuradio.digital.modulation_utils.type_1_mods diff --git a/docs/sphinx/source/eng_notation/index.rst b/docs/sphinx/source/eng_notation/index.rst new file mode 100644 index 000000000..f457754ac --- /dev/null +++ b/docs/sphinx/source/eng_notation/index.rst @@ -0,0 +1,8 @@ +gnuradio.eng_notation +===================== + +.. automodule:: gnuradio.eng_notation + +.. autofunction:: gnuradio.eng_notation.num_to_str +.. autofunction:: gnuradio.eng_notation.str_to_num + diff --git a/docs/sphinx/source/eng_option/index.rst b/docs/sphinx/source/eng_option/index.rst new file mode 100644 index 000000000..b9119ee69 --- /dev/null +++ b/docs/sphinx/source/eng_option/index.rst @@ -0,0 +1,6 @@ +gnuradio.eng_option +=================== + +.. automodule:: gnuradio.eng_option + +.. autoclass:: gnuradio.eng_option.eng_option diff --git a/docs/sphinx/source/fft.rst b/docs/sphinx/source/fft.rst new file mode 100644 index 000000000..79a0a4ed2 --- /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 new file mode 100644 index 000000000..e50b990bc --- /dev/null +++ b/docs/sphinx/source/gr/coding_blk.rst @@ -0,0 +1,11 @@ +gnuradio.gr: Information Coding and Decoding +============================================ + +.. 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 new file mode 100644 index 000000000..790109a94 --- /dev/null +++ b/docs/sphinx/source/gr/converter_blk.rst @@ -0,0 +1,32 @@ +gnuradio.gr: Type Conversions +============================= + +.. 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 new file mode 100644 index 000000000..4f800b642 --- /dev/null +++ b/docs/sphinx/source/gr/demodulation_blk.rst @@ -0,0 +1,4 @@ +gnuradio.gr: Demodulation +========================= + +.. autooldblock:: gnuradio.gr.quadrature_demod_cf diff --git a/docs/sphinx/source/gr/dft_blk.rst b/docs/sphinx/source/gr/dft_blk.rst new file mode 100644 index 000000000..4ac1d2e62 --- /dev/null +++ b/docs/sphinx/source/gr/dft_blk.rst @@ -0,0 +1,6 @@ +gnuradio.gr: Fourier Transform +============================== + +.. 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 new file mode 100644 index 000000000..a73ddda2a --- /dev/null +++ b/docs/sphinx/source/gr/filter_blk.rst @@ -0,0 +1,46 @@ +gnuradio.gr: Filters +==================== + +.. 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/filter_design.rst b/docs/sphinx/source/gr/filter_design.rst new file mode 100644 index 000000000..6ab23c50b --- /dev/null +++ b/docs/sphinx/source/gr/filter_design.rst @@ -0,0 +1,7 @@ +gnuradio.gr: Digital Filter Design +================================== + +.. autoclass:: gnuradio.gr.firdes + :members: + +.. autofunction:: gnuradio.gr.remez diff --git a/docs/sphinx/source/gr/index.rst b/docs/sphinx/source/gr/index.rst new file mode 100644 index 000000000..3d32599f1 --- /dev/null +++ b/docs/sphinx/source/gr/index.rst @@ -0,0 +1,380 @@ +gnuradio.gr +=========== + +.. automodule:: gnuradio.gr + +Signal Processing Blocks +------------------------ + +Top Block and Hierarchical Block Base Classes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.top_block + gnuradio.gr.hier_block2 + +Signal Sources +^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.glfsr_source_b + gnuradio.gr.glfsr_source_f + gnuradio.gr.lfsr_32k_source_s + gnuradio.gr.null_source + gnuradio.gr.noise_source_c + gnuradio.gr.noise_source_f + gnuradio.gr.noise_source_i + gnuradio.gr.noise_source_s + gnuradio.gr.sig_source_c + gnuradio.gr.sig_source_f + gnuradio.gr.sig_source_i + gnuradio.gr.sig_source_s + gnuradio.gr.vector_source_b + gnuradio.gr.vector_source_c + gnuradio.gr.vector_source_f + gnuradio.gr.vector_source_i + gnuradio.gr.vector_source_s + gnuradio.gr.file_descriptor_source + gnuradio.gr.file_source + gnuradio.gr.message_source + gnuradio.gr.udp_source + gnuradio.gr.wavfile_source + +Signal Sinks +^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.bin_statistics_f + gnuradio.gr.check_counting_s + gnuradio.gr.check_lfsr_32k_s + gnuradio.gr.framer_sink_1 + gnuradio.gr.null_sink + gnuradio.gr.packet_sink + gnuradio.gr.probe_avg_mag_sqrd_c + gnuradio.gr.probe_avg_mag_sqrd_cf + gnuradio.gr.probe_avg_mag_sqrd_f + gnuradio.gr.probe_signal_f + gnuradio.gr.vector_sink_b + gnuradio.gr.vector_sink_c + gnuradio.gr.vector_sink_f + gnuradio.gr.vector_sink_i + gnuradio.gr.vector_sink_s + gnuradio.gr.file_descriptor_sink + gnuradio.gr.file_sink + gnuradio.gr.histo_sink_f + gnuradio.gr.message_sink + gnuradio.gr.oscope_sink_f + gnuradio.gr.udp_sink + gnuradio.gr.wavfile_sink + +Filters +^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.fft_filter_ccc + gnuradio.gr.fft_filter_fff + gnuradio.gr.filter_delay_fc + gnuradio.gr.fir_filter_ccc + gnuradio.gr.fir_filter_ccf + gnuradio.gr.fir_filter_fcc + gnuradio.gr.fir_filter_fff + gnuradio.gr.fir_filter_fsf + gnuradio.gr.fir_filter_scc + gnuradio.gr.fractional_interpolator_cc + gnuradio.gr.fractional_interpolator_ff + gnuradio.gr.freq_xlating_fir_filter_ccc + gnuradio.gr.freq_xlating_fir_filter_ccf + gnuradio.gr.freq_xlating_fir_filter_fcc + gnuradio.gr.freq_xlating_fir_filter_fcf + gnuradio.gr.freq_xlating_fir_filter_scc + gnuradio.gr.freq_xlating_fir_filter_scf + gnuradio.gr.hilbert_fc + gnuradio.gr.iir_filter_ffd + gnuradio.gr.interp_fir_filter_ccc + gnuradio.gr.interp_fir_filter_ccf + gnuradio.gr.interp_fir_filter_fcc + gnuradio.gr.interp_fir_filter_fff + gnuradio.gr.interp_fir_filter_fsf + gnuradio.gr.interp_fir_filter_scc + gnuradio.gr.rational_resampler_base_ccc + gnuradio.gr.rational_resampler_base_ccf + gnuradio.gr.rational_resampler_base_fcc + gnuradio.gr.rational_resampler_base_fff + gnuradio.gr.rational_resampler_base_fsf + gnuradio.gr.rational_resampler_base_scc + gnuradio.gr.single_pole_iir_filter_cc + gnuradio.gr.single_pole_iir_filter_ff + gnuradio.gr.moving_average_cc + gnuradio.gr.moving_average_ff + gnuradio.gr.moving_average_ii + gnuradio.gr.moving_average_ss + gnuradio.gr.pfb_arb_resampler_ccf + gnuradio.gr.pfb_channelizer_ccf + gnuradio.gr.pfb_clock_sync_ccf + gnuradio.gr.pfb_clock_sync_fff + gnuradio.gr.pfb_decimator_ccf + gnuradio.gr.pfb_interpolator_ccf + +Mathematics +^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.conjugate_cc + gnuradio.gr.nlog10_ff + gnuradio.gr.rms_cf + gnuradio.gr.rms_ff + gnuradio.gr.add_cc + gnuradio.gr.add_const_cc + gnuradio.gr.add_const_ff + gnuradio.gr.add_const_ii + gnuradio.gr.add_const_sf + gnuradio.gr.add_const_ss + gnuradio.gr.add_const_vcc + gnuradio.gr.add_const_vff + gnuradio.gr.add_const_vii + gnuradio.gr.add_const_vss + gnuradio.gr.add_ff + gnuradio.gr.add_ii + gnuradio.gr.add_ss + gnuradio.gr.and_bb + gnuradio.gr.and_const_bb + gnuradio.gr.and_const_ii + gnuradio.gr.and_const_ss + gnuradio.gr.and_ii + gnuradio.gr.and_ss + gnuradio.gr.divide_cc + gnuradio.gr.divide_ff + gnuradio.gr.divide_ii + gnuradio.gr.divide_ss + gnuradio.gr.integrate_cc + gnuradio.gr.integrate_ff + gnuradio.gr.integrate_ii + gnuradio.gr.integrate_ss + gnuradio.gr.multiply_cc + gnuradio.gr.multiply_const_cc + gnuradio.gr.multiply_const_ff + gnuradio.gr.multiply_const_ii + gnuradio.gr.multiply_const_ss + gnuradio.gr.multiply_const_vcc + gnuradio.gr.multiply_const_vff + gnuradio.gr.multiply_const_vii + gnuradio.gr.multiply_const_vss + gnuradio.gr.multiply_ff + gnuradio.gr.multiply_ii + gnuradio.gr.multiply_ss + gnuradio.gr.not_bb + gnuradio.gr.not_ii + gnuradio.gr.not_ss + gnuradio.gr.or_bb + gnuradio.gr.or_ii + gnuradio.gr.or_ss + gnuradio.gr.sub_cc + gnuradio.gr.sub_ff + gnuradio.gr.sub_ii + gnuradio.gr.sub_ss + gnuradio.gr.xor_bb + gnuradio.gr.xor_ii + gnuradio.gr.xor_ss + +Modulation +^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.cpfsk_bc + gnuradio.gr.frequency_modulator_fc + gnuradio.gr.phase_modulator_fc + +Demodulation +^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.quadrature_demod_cf + +Information Coding and Decoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.additive_scrambler_bb + gnuradio.gr.descrambler_bb + gnuradio.gr.diff_decoder_bb + gnuradio.gr.diff_encoder_bb + gnuradio.gr.fake_channel_encoder_pp + gnuradio.gr.fake_channel_decoder_pp + gnuradio.gr.map_bb + gnuradio.gr.scrambler_bb + +Synchronization +^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.pll_carriertracking_cc + gnuradio.gr.pll_freqdet_cf + gnuradio.gr.pll_refout_cc + gnuradio.gr.pn_correlator_cc + gnuradio.gr.simple_correlator + gnuradio.gr.simple_framer + +Type Conversions +^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.bytes_to_syms + gnuradio.gr.char_to_float + gnuradio.gr.complex_to_interleaved_short + gnuradio.gr.complex_to_float + gnuradio.gr.complex_to_real + gnuradio.gr.complex_to_imag + gnuradio.gr.complex_to_mag + gnuradio.gr.complex_to_mag_squared + gnuradio.gr.complex_to_arg + gnuradio.gr.float_to_char + gnuradio.gr.float_to_complex + gnuradio.gr.float_to_short + gnuradio.gr.float_to_uchar + gnuradio.gr.interleaved_short_to_complex + gnuradio.gr.short_to_float + gnuradio.gr.uchar_to_float + gnuradio.gr.unpack_k_bits_bb + gnuradio.gr.chunks_to_symbols_bc + gnuradio.gr.chunks_to_symbols_bf + gnuradio.gr.chunks_to_symbols_ic + gnuradio.gr.chunks_to_symbols_if + gnuradio.gr.chunks_to_symbols_sc + gnuradio.gr.chunks_to_symbols_sf + gnuradio.gr.packed_to_unpacked_bb + gnuradio.gr.packed_to_unpacked_ii + gnuradio.gr.packed_to_unpacked_ss + gnuradio.gr.unpacked_to_packed_bb + gnuradio.gr.unpacked_to_packed_ii + gnuradio.gr.unpacked_to_packed_ss + +Signal Level Control (AGC) +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.agc2_cc + gnuradio.gr.agc2_ff + gnuradio.gr.agc_cc + gnuradio.gr.agc_ff + gnuradio.gr.ctcss_squelch_ff + gnuradio.gr.dpll_bb + gnuradio.gr.feedforward_agc_cc + gnuradio.gr.peak_detector2_fb + gnuradio.gr.pwr_squelch_cc + gnuradio.gr.pwr_squelch_ff + gnuradio.gr.regenerate_bb + gnuradio.gr.simple_squelch_cc + gnuradio.gr.mute_cc + gnuradio.gr.mute_ff + gnuradio.gr.mute_ii + gnuradio.gr.mute_ss + gnuradio.gr.peak_detector_fb + gnuradio.gr.peak_detector_ib + gnuradio.gr.peak_detector_sb + gnuradio.gr.sample_and_hold_bb + gnuradio.gr.sample_and_hold_ff + gnuradio.gr.sample_and_hold_ii + gnuradio.gr.sample_and_hold_ss + +Fourier Transform +^^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.goertzel_fc + gnuradio.gr.fft_vcc + gnuradio.gr.fft_vfc + +Miscellaneous Blocks +^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.copy + gnuradio.gr.delay + gnuradio.gr.kludge_copy + gnuradio.gr.nop + gnuradio.gr.pa_2x2_phase_combiner + gnuradio.gr.repeat + gnuradio.gr.threshold_ff + gnuradio.gr.throttle + gnuradio.gr.channel_model + +Slicing and Dicing Streams +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autosummary:: + :nosignatures: + + gnuradio.gr.deinterleave + gnuradio.gr.head + gnuradio.gr.interleave + gnuradio.gr.keep_one_in_n + gnuradio.gr.skiphead + gnuradio.gr.stream_to_streams + gnuradio.gr.stream_to_vector + gnuradio.gr.streams_to_stream + gnuradio.gr.streams_to_vector + gnuradio.gr.vector_to_stream + gnuradio.gr.vector_to_streams + +Digital Filter Design +--------------------- + +.. autosummary:: + :nosignatures: + + gnuradio.gr.firdes + gnuradio.gr.remez + +Miscellaneous +------------- + +.. autosummary:: + :nosignatures: + + gnuradio.gr.feval_dd + gnuradio.gr.feval_cc + gnuradio.gr.feval_ll + gnuradio.gr.feval + gnuradio.gr.prefs + gnuradio.gr.test + gnuradio.gr.message + gnuradio.gr.msg_queue + gnuradio.gr.enable_realtime_scheduling + +Implementation Details +---------------------- + +.. autosummary:: + :nosignatures: + + gnuradio.gr.block_detail + gnuradio.gr.buffer + gnuradio.gr.dispatcher + gnuradio.gr.single_threaded_scheduler + diff --git a/docs/sphinx/source/gr/internal.rst b/docs/sphinx/source/gr/internal.rst new file mode 100644 index 000000000..4948b38d4 --- /dev/null +++ b/docs/sphinx/source/gr/internal.rst @@ -0,0 +1,7 @@ +gnuradio.gr: Implementation Details +=================================== + +.. autofunction:: gnuradio.gr.block_detail +.. autofunction:: gnuradio.gr.buffer +.. autofunction:: gnuradio.gr.dispatcher +.. autofunction:: gnuradio.gr.single_threaded_scheduler diff --git a/docs/sphinx/source/gr/level_blk.rst b/docs/sphinx/source/gr/level_blk.rst new file mode 100644 index 000000000..d6c565c65 --- /dev/null +++ b/docs/sphinx/source/gr/level_blk.rst @@ -0,0 +1,26 @@ +gnuradio.gr: Signal Level Control (AGC) +======================================= + +.. 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 new file mode 100644 index 000000000..7b9437f99 --- /dev/null +++ b/docs/sphinx/source/gr/math_blk.rst @@ -0,0 +1,59 @@ +gnuradio.gr: Mathematics +======================== + +.. 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.rst b/docs/sphinx/source/gr/misc.rst new file mode 100644 index 000000000..b0a3f3ba1 --- /dev/null +++ b/docs/sphinx/source/gr/misc.rst @@ -0,0 +1,12 @@ +gnuradio.gr: Miscellaneous +========================== + +.. autofunction:: gnuradio.gr.feval_dd +.. autofunction:: gnuradio.gr.feval_cc +.. autofunction:: gnuradio.gr.feval_ll +.. autofunction:: gnuradio.gr.feval +.. autofunction:: gnuradio.gr.prefs +.. autofunction:: gnuradio.gr.test +.. autofunction:: gnuradio.gr.message +.. autofunction:: gnuradio.gr.msg_queue +.. autofunction:: gnuradio.gr.enable_realtime_scheduling diff --git a/docs/sphinx/source/gr/misc_blk.rst b/docs/sphinx/source/gr/misc_blk.rst new file mode 100644 index 000000000..c69293056 --- /dev/null +++ b/docs/sphinx/source/gr/misc_blk.rst @@ -0,0 +1,12 @@ +gnuradio.gr: Miscellaneous Blocks +================================= + +.. 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 new file mode 100644 index 000000000..1fff4614c --- /dev/null +++ b/docs/sphinx/source/gr/modulation_blk.rst @@ -0,0 +1,6 @@ +gnuradio.gr: Modulation +======================= + +.. 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 new file mode 100644 index 000000000..7608ff09b --- /dev/null +++ b/docs/sphinx/source/gr/sink_blk.rst @@ -0,0 +1,25 @@ +gnuradio.gr: Signal Sinks +========================= + +.. 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 new file mode 100644 index 000000000..e845627aa --- /dev/null +++ b/docs/sphinx/source/gr/slicedice_blk.rst @@ -0,0 +1,14 @@ +gnuradio.gr: Slicing and Dicing 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 new file mode 100644 index 000000000..df873bcf7 --- /dev/null +++ b/docs/sphinx/source/gr/source_blk.rst @@ -0,0 +1,26 @@ +gnuradio.gr: Signal Sources +=========================== + +.. 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 new file mode 100644 index 000000000..be9f908f7 --- /dev/null +++ b/docs/sphinx/source/gr/sync_blk.rst @@ -0,0 +1,9 @@ +gnuradio.gr: Synchronization +============================ + +.. 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/gr/top_block.rst b/docs/sphinx/source/gr/top_block.rst new file mode 100644 index 000000000..3d4e9ef3d --- /dev/null +++ b/docs/sphinx/source/gr/top_block.rst @@ -0,0 +1,7 @@ +gnuradio.gr: Top Block and Hierarchical Block Base Classes +========================================================== + +.. autoclass:: gnuradio.gr.top_block + +.. autoclass:: gnuradio.gr.hier_block2 + diff --git a/docs/sphinx/source/gr_unittest/index.rst b/docs/sphinx/source/gr_unittest/index.rst new file mode 100644 index 000000000..2169a7da4 --- /dev/null +++ b/docs/sphinx/source/gr_unittest/index.rst @@ -0,0 +1,7 @@ +gnuradio.gr_unittest +==================== + +.. automodule:: gnuradio.gr_unittest + +.. autoclass:: gnuradio.gr_unittest.TestCase +.. autofunction:: gnuradio.gr_unittest.run diff --git a/docs/sphinx/source/index.rst b/docs/sphinx/source/index.rst new file mode 100644 index 000000000..38d859aaf --- /dev/null +++ b/docs/sphinx/source/index.rst @@ -0,0 +1,120 @@ +gnuradio +======== + +.. automodule:: gnuradio + +Core Framework +-------------- + +.. autosummary:: + :nosignatures: + + gnuradio.gr + gnuradio.digital + gnuradio.blks2 + gnuradio.audio + gnuradio.trellis + gnuradio.wavelet + gnuradio.fft + gnuradio.window + gnuradio.optfir + gnuradio.gr_unittest + gnuradio.qtgui + gnuradio.wxgui + +.. toctree:: + :hidden: + + gnuradio.gr <gr/index> + gnuradio.digital <digital/index> + gnuradio.blks2 <blks2/index> + gnuradio.audio <audio/index> + gnuradio.gr_unittest <gr_unittest/index> + 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> + +Utilities +--------- + +.. autosummary:: + :nosignatures: + + gnuradio.plot_data + gnuradio.eng_notation + gnuradio.eng_option + +.. toctree:: + :hidden: + + gnuradio.plot_data <plot_data> + gnuradio.eng_notation <eng_notation/index> + gnuradio.eng_option <eng_option/index> + +Framework Extensions +-------------------- + +.. autosummary:: + :nosignatures: + + gnuradio.atsc + gnuradio.noaa + gnuradio.pager + gnuradio.video_sdl + gnuradio.vocoder + +.. toctree:: + :hidden: + + gnuradio.atsc <atsc/index> + gnuradio.noaa <noaa> + gnuradio.pager <pager/index> + gnuradio.video_sdl <video_sdl> + gnuradio.vocoder <vocoder/index> + + +.. Use this to add to the toctree but not displayed +.. It's mostly to get rid of warnings + +.. toctree:: + :hidden: + + coding <gr/coding_blk> + converter <gr/converter_blk> + demodulation <gr/demodulation_blk> + dft <gr/dft_blk> + filter <gr/filter_blk> + filter_design <gr/filter_design> + internal <gr/internal> + level <gr/level_blk> + math <gr/math_blk> + misc <gr/misc> + misc <gr/misc_blk> + modulation <gr/modulation_blk> + sink <gr/sink_blk> + slicedice <gr/slicedice_blk> + source <gr/source_blk> + sync <gr/sync_blk> + top_block <gr/top_block> + + atsc_blks <atsc/blks> + blks <blks2/blks> + blks2_utilities <blks2/utilities> + digital_blocks <digital/blocks> + constellations <digital/constellations> + ofdm <digital/ofdm> + pkt_utils <digital/pkt_utils> + digital_utilities <digital/utilities> + optfir <optfir/detail> + pager_blks <pager/blks> + pyqt_filter <pyqt_filter> + pyqt_plot <pyqt_plot> + trellis_blks <trellis/blks> + trellis_objs <trellis/objs> + vocoder_blks <vocoder/blks> + window_detail <window/detail> + wxgui_blks <wxgui/blks> diff --git a/docs/sphinx/source/noaa.rst b/docs/sphinx/source/noaa.rst new file mode 100644 index 000000000..65461f99b --- /dev/null +++ b/docs/sphinx/source/noaa.rst @@ -0,0 +1,8 @@ +gnuradio.noaa +============== + +.. automodule:: gnuradio.noaa + +.. autooldblock:: gnuradio.noaa.hrpt_decoder +.. autooldblock:: gnuradio.noaa.hrpt_deframer +.. autooldblock:: gnuradio.noaa.hrpt_pll_cf diff --git a/docs/sphinx/source/optfir/detail.rst b/docs/sphinx/source/optfir/detail.rst new file mode 100644 index 000000000..78807bee0 --- /dev/null +++ b/docs/sphinx/source/optfir/detail.rst @@ -0,0 +1,14 @@ +gnuradio.optfir +=============== + +.. autofunction:: gnuradio.optfir.band_pass +.. autofunction:: gnuradio.optfir.band_reject +.. autofunction:: gnuradio.optfir.bporder +.. autofunction:: gnuradio.optfir.complex_band_pass +.. autofunction:: gnuradio.optfir.high_pass +.. autofunction:: gnuradio.optfir.low_pass +.. autofunction:: gnuradio.optfir.lporder +.. autofunction:: gnuradio.optfir.passband_ripple_to_dev +.. autofunction:: gnuradio.optfir.remez +.. autofunction:: gnuradio.optfir.remezord +.. autofunction:: gnuradio.optfir.stopband_atten_to_dev diff --git a/docs/sphinx/source/optfir/index.rst b/docs/sphinx/source/optfir/index.rst new file mode 100644 index 000000000..f49b01a1f --- /dev/null +++ b/docs/sphinx/source/optfir/index.rst @@ -0,0 +1,19 @@ +gnuradio.optfir +=============== + +.. automodule:: gnuradio.optfir + +.. autosummary:: + :nosignatures: + + gnuradio.optfir.band_pass + gnuradio.optfir.band_reject + gnuradio.optfir.bporder + gnuradio.optfir.complex_band_pass + gnuradio.optfir.high_pass + gnuradio.optfir.low_pass + gnuradio.optfir.lporder + gnuradio.optfir.passband_ripple_to_dev + gnuradio.optfir.remez + gnuradio.optfir.remezord + gnuradio.optfir.stopband_atten_to_dev diff --git a/docs/sphinx/source/pager/blks.rst b/docs/sphinx/source/pager/blks.rst new file mode 100644 index 000000000..a36103d1f --- /dev/null +++ b/docs/sphinx/source/pager/blks.rst @@ -0,0 +1,9 @@ +gnuradio.pager: Signal Processing Blocks +======================================== + +.. autooldblock:: gnuradio.pager.flex_deinterleave +.. autopyblock:: gnuradio.pager.flex_demod +.. 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/pager/index.rst b/docs/sphinx/source/pager/index.rst new file mode 100644 index 000000000..36df48451 --- /dev/null +++ b/docs/sphinx/source/pager/index.rst @@ -0,0 +1,23 @@ +gnuradio.pager +============== + +.. automodule:: gnuradio.pager + +Signal Processing Blocks +------------------------ + +.. autosummary:: + :nosignatures: + + gnuradio.pager.flex_deinterleave + gnuradio.pager.flex_demod + gnuradio.pager.flex_frame + gnuradio.pager.flex_parse + gnuradio.pager.flex_sync + gnuradio.pager.pager_flex_frame + gnuradio.pager.slicer_fb + +Utility Functions +----------------- + +.. autofunction:: gnuradio.pager.queue_runner diff --git a/docs/sphinx/source/plot_data.rst b/docs/sphinx/source/plot_data.rst new file mode 100644 index 000000000..1b52a083c --- /dev/null +++ b/docs/sphinx/source/plot_data.rst @@ -0,0 +1,6 @@ +gnuradio.plot_data +================== + +.. automodule:: gnuradio.plot_data + +.. autoclass:: gnuradio.plot_data.plot_data diff --git a/docs/sphinx/source/pyqt_filter.rst b/docs/sphinx/source/pyqt_filter.rst new file mode 100644 index 000000000..cc52abfa7 --- /dev/null +++ b/docs/sphinx/source/pyqt_filter.rst @@ -0,0 +1,6 @@ +gnuradio.pyqt_filter +==================== + +.. automodule:: gnuradio.pyqt_filter + +.. autoclass:: gnuradio.pyqt_filter.Ui_MainWindow diff --git a/docs/sphinx/source/pyqt_plot.rst b/docs/sphinx/source/pyqt_plot.rst new file mode 100644 index 000000000..3537a080b --- /dev/null +++ b/docs/sphinx/source/pyqt_plot.rst @@ -0,0 +1,6 @@ +gnuradio.pyqt_plot +================== + +.. automodule:: gnuradio.pyqt_plot + +.. autoclass:: gnuradio.pyqt_plot.Ui_MainWindow diff --git a/docs/sphinx/source/qtgui/index.rst b/docs/sphinx/source/qtgui/index.rst new file mode 100644 index 000000000..83bdedca8 --- /dev/null +++ b/docs/sphinx/source/qtgui/index.rst @@ -0,0 +1,9 @@ +gnuradio.qtgui +============== + +.. automodule:: gnuradio.qtgui + +.. 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 new file mode 100644 index 000000000..d82319bad --- /dev/null +++ b/docs/sphinx/source/trellis/blks.rst @@ -0,0 +1,62 @@ +gnuradio.trellis: Signal Processing Blocks +========================================== + +.. 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/trellis/index.rst b/docs/sphinx/source/trellis/index.rst new file mode 100644 index 000000000..8a451a913 --- /dev/null +++ b/docs/sphinx/source/trellis/index.rst @@ -0,0 +1,90 @@ +gnuradio.trellis +================ + +.. automodule:: gnuradio.trellis + +Object Classes +-------------- + +.. autosummary:: + :nosignatures: + + gnuradio.trellis.fsm + gnuradio.trellis.interleaver + +Signal Processing Blocks +------------------------ + +.. autosummary:: + :nosignatures: + + gnuradio.trellis.constellation_metrics_cf + gnuradio.trellis.encoder_bb + gnuradio.trellis.encoder_bi + gnuradio.trellis.encoder_bs + gnuradio.trellis.encoder_ii + gnuradio.trellis.encoder_si + gnuradio.trellis.encoder_ss + gnuradio.trellis.metrics_c + gnuradio.trellis.metrics_f + gnuradio.trellis.metrics_i + gnuradio.trellis.metrics_s + gnuradio.trellis.pccc_decoder_b + gnuradio.trellis.pccc_decoder_combined_cb + gnuradio.trellis.pccc_decoder_combined_ci + gnuradio.trellis.pccc_decoder_combined_cs + gnuradio.trellis.pccc_decoder_combined_fb + gnuradio.trellis.pccc_decoder_combined_fi + gnuradio.trellis.pccc_decoder_combined_fs + gnuradio.trellis.pccc_decoder_i + gnuradio.trellis.pccc_decoder_s + gnuradio.trellis.pccc_encoder_bb + gnuradio.trellis.pccc_encoder_bi + gnuradio.trellis.pccc_encoder_bs + gnuradio.trellis.pccc_encoder_ii + gnuradio.trellis.pccc_encoder_si + gnuradio.trellis.pccc_encoder_ss + gnuradio.trellis.permutation + gnuradio.trellis.sccc_decoder_b + gnuradio.trellis.sccc_decoder_combined_cb + gnuradio.trellis.sccc_decoder_combined_ci + gnuradio.trellis.sccc_decoder_combined_cs + gnuradio.trellis.sccc_decoder_combined_fb + gnuradio.trellis.sccc_decoder_combined_fi + gnuradio.trellis.sccc_decoder_combined_fs + gnuradio.trellis.sccc_decoder_i + gnuradio.trellis.sccc_decoder_s + gnuradio.trellis.sccc_encoder_bb + gnuradio.trellis.sccc_encoder_bi + gnuradio.trellis.sccc_encoder_bs + gnuradio.trellis.sccc_encoder_ii + gnuradio.trellis.sccc_encoder_si + gnuradio.trellis.sccc_encoder_ss + gnuradio.trellis.siso_combined_f + gnuradio.trellis.siso_f + gnuradio.trellis.viterbi_b + gnuradio.trellis.viterbi_combined_cb + gnuradio.trellis.viterbi_combined_ci + gnuradio.trellis.viterbi_combined_cs + gnuradio.trellis.viterbi_combined_fb + gnuradio.trellis.viterbi_combined_fi + gnuradio.trellis.viterbi_combined_fs + gnuradio.trellis.viterbi_combined_ib + gnuradio.trellis.viterbi_combined_ii + gnuradio.trellis.viterbi_combined_is + gnuradio.trellis.viterbi_combined_sb + gnuradio.trellis.viterbi_combined_si + gnuradio.trellis.viterbi_combined_ss + gnuradio.trellis.viterbi_i + gnuradio.trellis.viterbi_s + +Constants +--------- + +.. autosummary:: + :nosignatures: + + gnuradio.trellis.TRELLIS_MIN_SUM + gnuradio.trellis.TRELLIS_SUM_PRODUCT + + diff --git a/docs/sphinx/source/trellis/objs.rst b/docs/sphinx/source/trellis/objs.rst new file mode 100644 index 000000000..b3a4b7a4a --- /dev/null +++ b/docs/sphinx/source/trellis/objs.rst @@ -0,0 +1,5 @@ +gnuradio.trellis: Object Classes +-------------------------------- + +.. autoclass:: gnuradio.trellis.fsm +.. autoclass:: gnuradio.trellis.interleaver diff --git a/docs/sphinx/source/video_sdl.rst b/docs/sphinx/source/video_sdl.rst new file mode 100644 index 000000000..6be88d788 --- /dev/null +++ b/docs/sphinx/source/video_sdl.rst @@ -0,0 +1,7 @@ +gnuradio.video_sdl +================== + +.. automodule:: gnuradio.video_sdl + +.. 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 new file mode 100644 index 000000000..34eda9d25 --- /dev/null +++ b/docs/sphinx/source/vocoder/blks.rst @@ -0,0 +1,19 @@ +gnuradio.vocoder +================ + +.. 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/vocoder/index.rst b/docs/sphinx/source/vocoder/index.rst new file mode 100644 index 000000000..2e3180995 --- /dev/null +++ b/docs/sphinx/source/vocoder/index.rst @@ -0,0 +1,26 @@ +gnuradio.vocoder +================ + +.. automodule:: gnuradio.vocoder + +.. autosummary:: + :nosignatures: + + gnuradio.vocoder.alaw_decode_bs + gnuradio.vocoder.alaw_encode_sb + gnuradio.vocoder.codec2_decode_ps + gnuradio.vocoder.codec2_encode_sp + gnuradio.vocoder.cvsd_decode_bf + gnuradio.vocoder.cvsd_decode_bs + gnuradio.vocoder.cvsd_encode_fb + gnuradio.vocoder.cvsd_encode_sb + gnuradio.vocoder.g721_decode_bs + gnuradio.vocoder.g721_encode_sb + gnuradio.vocoder.g723_24_decode_bs + gnuradio.vocoder.g723_24_encode_sb + gnuradio.vocoder.g723_40_decode_bs + gnuradio.vocoder.g723_40_encode_sb + gnuradio.vocoder.gsm_fr_decode_ps + gnuradio.vocoder.gsm_fr_encode_sp + gnuradio.vocoder.ulaw_decode_bs + gnuradio.vocoder.ulaw_encode_sb diff --git a/docs/sphinx/source/wavelet.rst b/docs/sphinx/source/wavelet.rst new file mode 100644 index 000000000..5236c4dbb --- /dev/null +++ b/docs/sphinx/source/wavelet.rst @@ -0,0 +1,8 @@ +gnuradio.wavelet +================ + +.. automodule:: gnuradio.wavelet + +.. autooldblock:: gnuradio.wavelet.squash_ff +.. autooldblock:: gnuradio.wavelet.wavelet_ff +.. autooldblock:: gnuradio.wavelet.wvps_ff diff --git a/docs/sphinx/source/window/detail.rst b/docs/sphinx/source/window/detail.rst new file mode 100644 index 000000000..7222a0cb4 --- /dev/null +++ b/docs/sphinx/source/window/detail.rst @@ -0,0 +1,20 @@ +gnuradio.window +=============== + +.. autofunction:: gnuradio.window.bartlett +.. autofunction:: gnuradio.window.blackman2 +.. autofunction:: gnuradio.window.blackman3 +.. autofunction:: gnuradio.window.blackman4 +.. autofunction:: gnuradio.window.blackmanharris +.. autofunction:: gnuradio.window.coswindow +.. autofunction:: gnuradio.window.exponential +.. autofunction:: gnuradio.window.flattop +.. autofunction:: gnuradio.window.hamming +.. autofunction:: gnuradio.window.hanning +.. autofunction:: gnuradio.window.kaiser +.. autofunction:: gnuradio.window.nuttall +.. autofunction:: gnuradio.window.nuttall_cfd +.. autofunction:: gnuradio.window.parzen +.. autofunction:: gnuradio.window.rectangular +.. autofunction:: gnuradio.window.riemann +.. autofunction:: gnuradio.window.welch diff --git a/docs/sphinx/source/window/index.rst b/docs/sphinx/source/window/index.rst new file mode 100644 index 000000000..6ecfea0e9 --- /dev/null +++ b/docs/sphinx/source/window/index.rst @@ -0,0 +1,25 @@ +gnuradio.window +=============== + +.. automodule:: gnuradio.window + +.. autosummary:: + :nosignatures: + + gnuradio.window.bartlett + gnuradio.window.blackman2 + gnuradio.window.blackman3 + gnuradio.window.blackman4 + gnuradio.window.blackmanharris + gnuradio.window.coswindow + gnuradio.window.exponential + gnuradio.window.flattop + gnuradio.window.hamming + gnuradio.window.hanning + gnuradio.window.kaiser + gnuradio.window.nuttall + gnuradio.window.nuttall_cfd + gnuradio.window.parzen + gnuradio.window.rectangular + gnuradio.window.riemann + gnuradio.window.welch diff --git a/docs/sphinx/source/wxgui/blks.rst b/docs/sphinx/source/wxgui/blks.rst new file mode 100644 index 000000000..c304ea0a8 --- /dev/null +++ b/docs/sphinx/source/wxgui/blks.rst @@ -0,0 +1,13 @@ +gnuradio.wxgui +===================== + +.. autopyblock:: gnuradio.wxgui.constsink_gl.const_sink_c +.. autopyblock:: gnuradio.wxgui.fftsink2.fft_sink_c +.. autopyblock:: gnuradio.wxgui.fftsink2.fft_sink_f +.. autopyblock:: gnuradio.wxgui.histosink_gl.histo_sink_f +.. autopyblock:: gnuradio.wxgui.numbersink2.number_sink_c +.. autopyblock:: gnuradio.wxgui.numbersink2.number_sink_f +.. autopyblock:: gnuradio.wxgui.scopesink2.scope_sink_c +.. autopyblock:: gnuradio.wxgui.scopesink2.scope_sink_f +.. autopyblock:: gnuradio.wxgui.waterfallsink2.waterfall_sink_c +.. autopyblock:: gnuradio.wxgui.waterfallsink2.waterfall_sink_f diff --git a/docs/sphinx/source/wxgui/index.rst b/docs/sphinx/source/wxgui/index.rst new file mode 100644 index 000000000..f3fa4f337 --- /dev/null +++ b/docs/sphinx/source/wxgui/index.rst @@ -0,0 +1,18 @@ +gnuradio.wxgui +============== + +.. automodule:: gnuradio.wxgui + +.. autosummary:: + :nosignatures: + + gnuradio.wxgui.common.const_sink_c + gnuradio.wxgui.fftsink2.fft_sink_c + gnuradio.wxgui.fftsink2.fft_sink_f + gnuradio.wxgui.histosink_gl.histosink_f + gnuradio.wxgui.numbersink2.number_sink_c + gnuradio.wxgui.numbersink2.number_sink_f + gnuradio.wxgui.scopesink2.scope_sink_c + gnuradio.wxgui.scopesink2.scope_sink_f + gnuradio.wxgui.waterfallsink2.waterfall_sink_c + gnuradio.wxgui.waterfallsink2.waterfall_sink_f diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt index 207d85c4c..0ad55e38a 100644 --- a/gnuradio-core/src/lib/general/CMakeLists.txt +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -281,6 +281,7 @@ 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 diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i index cd8c279c9..54d9a8670 100644 --- a/gnuradio-core/src/lib/general/general.i +++ b/gnuradio-core/src/lib/general/general.i @@ -137,6 +137,7 @@ #include <gr_cpm.h> #include <gr_correlate_access_code_tag_bb.h> #include <gr_add_ff.h> +#include <gr_vector_map.h> %} %include "gri_control_loop.i" @@ -254,3 +255,4 @@ %include "gr_cpm.i" %include "gr_correlate_access_code_tag_bb.i" %include "gr_add_ff.i" +%include "gr_vector_map.i" 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 000000000..2a13efb06 --- /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 000000000..f5492b1e3 --- /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_vector_map.i b/gnuradio-core/src/lib/general/gr_vector_map.i new file mode 100644 index 000000000..e9fa3f27e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_map.i @@ -0,0 +1,28 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr, vector_map); + +%template() std::vector<size_t>; +%template() std::vector< std::vector< std::vector<size_t> > >; + +%include "gr_vector_map.h" diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i index 239223851..3a421ad5d 100644 --- a/gnuradio-core/src/lib/swig/gnuradio.i +++ b/gnuradio-core/src/lib/swig/gnuradio.i @@ -20,6 +20,9 @@ * Boston, MA 02110-1301, USA. */ +// Disable warning about base class types +#pragma SWIG nowarn=401 + //////////////////////////////////////////////////////////////////////// // gnuradio.i // SWIG interface definition diff --git a/gnuradio-core/src/lib/swig/gr_swig_block_magic.i b/gnuradio-core/src/lib/swig/gr_swig_block_magic.i index cdc9fbe49..4016ae772 100644 --- a/gnuradio-core/src/lib/swig/gr_swig_block_magic.i +++ b/gnuradio-core/src/lib/swig/gr_swig_block_magic.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2010 Free Software Foundation, Inc. + * Copyright 2004,2010,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -40,3 +40,11 @@ FULL_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), %} %enddef #endif + +%define GR_SWIG_BLOCK_MAGIC2(PKG, BASE_NAME) +%template(BASE_NAME ## _sptr) boost::shared_ptr<gr:: ## PKG ## :: ## BASE_NAME>; +%pythoncode %{ +BASE_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id()) +BASE_NAME = BASE_NAME.make; +%} +%enddef diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py index 0660941d5..ce0757912 100644 --- a/gnuradio-core/src/python/build_utils.py +++ b/gnuradio-core/src/python/build_utils.py @@ -176,11 +176,11 @@ def is_complex (code3): return '0' -def standard_dict (name, code3): +def standard_dict (name, code3, package='gr'): d = {} d['NAME'] = name d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper () - d['BASE_NAME'] = re.sub ('^gr_', '', name) + 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['COPYRIGHT'] = copyright 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 000000000..12f4be589 --- /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-digital/grc/digital_additive_scrambler_bb.xml b/gr-digital/grc/digital_additive_scrambler_bb.xml new file mode 100644 index 000000000..5ae5ba06f --- /dev/null +++ b/gr-digital/grc/digital_additive_scrambler_bb.xml @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Additive Scrambler +################################################### + --> +<block> + <name>Additive Scrambler</name> + <key>digital_additive_scrambler_bb</key> + <import>from gnuradio import digital</import> + <make>digital.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/gr-digital/grc/digital_block_tree.xml b/gr-digital/grc/digital_block_tree.xml index 3ef4d0b1d..9efa0d3fb 100644 --- a/gr-digital/grc/digital_block_tree.xml +++ b/gr-digital/grc/digital_block_tree.xml @@ -30,19 +30,35 @@ <name></name> <!-- Blank for Root Name --> <cat> <name>Digital</name> + <block>digital_additive_scrambler_bb</block> <block>digital_binary_slicer_fb</block> + <block>digital_bytes_to_syms</block> + <block>digital_chunks_to_symbols_xx</block> <block>digital_clock_recovery_mm_xx</block> <block>digital_cma_equalizer_cc</block> <block>digital_constellation_decoder_cb</block> <block>digital_constellation_receiver_cb</block> <block>digital_correlate_access_code_bb</block> <block>digital_costas_loop_cc</block> + <block>digital_descrambler_bb</block> <block>digital_fll_band_edge_cc</block> + <block>digital_glfsr_source_x</block> <block>digital_kurtotic_equalizer_cc</block> <block>digital_lms_dd_equalizer_cc</block> + <block>digital_map_bb</block> <block>digital_mpsk_receiver_cc</block> <block>digital_mpsk_snr_est_cc</block> + <block>digital_pfb_clock_sync_xxx</block> + <block>digital_pn_correlator_cc</block> + <block>digital_probe_density_b</block> <block>digital_probe_mpsk_snr_est_c</block> + <block>digital_scrambler_bb</block> + <block>digital_diff_decoder_bb</block> + <block>digital_diff_encoder_bb</block> + <block>digital_diff_phasor_cc</block> + <block>digital_framer_sink_1</block> + <block>digital_packet_sink</block> + <block>digital_simple_framer</block> </cat> <cat> <name>Digital Modulators</name> diff --git a/gr-digital/grc/digital_bytes_to_syms.xml b/gr-digital/grc/digital_bytes_to_syms.xml new file mode 100644 index 000000000..fb17bb6de --- /dev/null +++ b/gr-digital/grc/digital_bytes_to_syms.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Bytes to Syms +################################################### + --> +<block> + <name>Bytes to Symbols</name> + <key>digital_bytes_to_syms</key> + <import>from gnuradio import digital</import> + <make>digital.bytes_to_syms()</make> + <sink> + <name>in</name> + <type>byte</type> + </sink> + <source> + <name>out</name> + <type>float</type> + </source> +</block> diff --git a/gr-digital/grc/digital_chunks_to_symbols.xml b/gr-digital/grc/digital_chunks_to_symbols.xml new file mode 100644 index 000000000..494be274d --- /dev/null +++ b/gr-digital/grc/digital_chunks_to_symbols.xml @@ -0,0 +1,77 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Chunks to Symbols +################################################### + --> +<block> + <name>Chunks to Symbols</name> + <key>digital_chunks_to_symbols_xx</key> + <import>from gnuradio import digital</import> + <make>digital.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/gr-digital/grc/digital_descrambler_bb.xml b/gr-digital/grc/digital_descrambler_bb.xml new file mode 100644 index 000000000..4f52c7964 --- /dev/null +++ b/gr-digital/grc/digital_descrambler_bb.xml @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Descrambler +################################################### + --> +<block> + <name>Descrambler</name> + <key>digital_descrambler_bb</key> + <import>from gnuradio import digital</import> + <make>digital.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/gr-digital/grc/digital_diff_decoder_bb.xml b/gr-digital/grc/digital_diff_decoder_bb.xml new file mode 100644 index 000000000..a7c94b834 --- /dev/null +++ b/gr-digital/grc/digital_diff_decoder_bb.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Differential Decoder +################################################### + --> +<block> + <name>Differential Decoder</name> + <key>digital_diff_decoder_bb</key> + <import>from gnuradio import digital</import> + <make>digital.diff_decoder_bb($modulus)</make> + <param> + <name>Modulus</name> + <key>modulus</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/gr-digital/grc/digital_diff_encoder_bb.xml b/gr-digital/grc/digital_diff_encoder_bb.xml new file mode 100644 index 000000000..3885bed9a --- /dev/null +++ b/gr-digital/grc/digital_diff_encoder_bb.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Differential Encoder +################################################### + --> +<block> + <name>Differential Encoder</name> + <key>digital_diff_encoder_bb</key> + <import>from gnuradio import digital</import> + <make>digital.diff_encoder_bb($modulus)</make> + <param> + <name>Modulus</name> + <key>modulus</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/gr-digital/grc/digital_diff_phasor_cc.xml b/gr-digital/grc/digital_diff_phasor_cc.xml new file mode 100644 index 000000000..506bf400b --- /dev/null +++ b/gr-digital/grc/digital_diff_phasor_cc.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Differential Phasor +################################################### + --> +<block> + <name>Differential Phasor</name> + <key>digital_diff_phasor_cc</key> + <import>from gnuradio import digital</import> + <make>digital.diff_phasor_cc()</make> + <sink> + <name>in</name> + <type>complex</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-digital/grc/digital_framer_sink_1.xml b/gr-digital/grc/digital_framer_sink_1.xml new file mode 100644 index 000000000..9124e6d0d --- /dev/null +++ b/gr-digital/grc/digital_framer_sink_1.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Framer Sink 1 +################################################### + --> +<block> + <name>Framer Sink 1</name> + <key>digital_framer_sink_1</key> + <import>from gnuradio import digital</import> + <make>digital.framer_sink_1($target_queue)</make> + <param> + <name>Target Message Queue</name> + <key>target_queue</key> + <type>raw</type> + </param> + <sink> + <name>in</name> + <type>byte</type> + </sink> +</block> diff --git a/gr-digital/grc/digital_glfsr_source_x.xml b/gr-digital/grc/digital_glfsr_source_x.xml new file mode 100644 index 000000000..654dfa71c --- /dev/null +++ b/gr-digital/grc/digital_glfsr_source_x.xml @@ -0,0 +1,61 @@ +<?xml version="1.0"?> +<!-- +################################################### +##GLFSR Source +################################################### + --> +<block> + <name>GLFSR Source</name> + <key>digital_glfsr_source_x</key> + <import>from gnuradio import digital</import> + <make>digital.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> + <value>0</value> + <type>int</type> + </param> + <param> + <name>Seed</name> + <key>seed</key> + <value>1</value> + <type>int</type> + </param> + <source> + <name>out</name> + <type>$type</type> + </source> +</block> diff --git a/gr-digital/grc/digital_map_bb.xml b/gr-digital/grc/digital_map_bb.xml new file mode 100644 index 000000000..1435c5ac7 --- /dev/null +++ b/gr-digital/grc/digital_map_bb.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Map +################################################### + --> +<block> + <name>Map</name> + <key>digital_map_bb</key> + <import>from gnuradio import digital</import> + <make>digital.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/gr-digital/grc/digital_packet_sink.xml b/gr-digital/grc/digital_packet_sink.xml new file mode 100644 index 000000000..e9231bd05 --- /dev/null +++ b/gr-digital/grc/digital_packet_sink.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Packet Sink +################################################### + --> +<block> + <name>Packet Sink</name> + <key>digital_packet_sink</key> + <import>from gnuradio import digital</import> + <make>digital.packet_sink($sync_vector, $target_queue, $threshold)</make> + <param> + <name>Sync Vector</name> + <key>sync_vector</key> + <type>int_vector</type> + </param> + <param> + <name>Target Message Queue</name> + <key>target_queue</key> + <type>raw</type> + </param> + <param> + <name>Threshold</name> + <key>threshold</key> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>float</type> + </sink> +</block> diff --git a/gr-digital/grc/digital_pfb_clock_sync.xml b/gr-digital/grc/digital_pfb_clock_sync.xml new file mode 100644 index 000000000..9e2a4cd5e --- /dev/null +++ b/gr-digital/grc/digital_pfb_clock_sync.xml @@ -0,0 +1,104 @@ +<?xml version="1.0"?> +<!-- +################################################### +## Polyphase Filter based Clock Sync +################################################### + --> +<block> + <name>Polyphase Clock Sync</name> + <key>digital_pfb_clock_sync_xxx</key> + <import>from gnuradio import digital</import> + <make>digital.pfb_clock_sync_$(type)($sps, $alpha, $taps, $filter_size, $init_phase, $max_dev, $osps) +self.$(id).set_beta($beta)</make> + <callback>set_taps($taps)</callback> + <callback>set_alpha($alpha)</callback> + <callback>set_beta($beta)</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>Samples/Symbol</name> + <key>sps</key> + <type>real</type> + </param> + <param> + <name>Alpha</name> + <key>alpha</key> + <type>real</type> + </param> + <param> + <name>Beta</name> + <key>beta</key> + <type>real</type> + </param> + <param> + <name>Taps</name> + <key>taps</key> + <type>real_vector</type> + </param> + <param> + <name>Filter Size</name> + <key>filter_size</key> + <value>32</value> + <type>int</type> + </param> + <param> + <name>Initial Phase</name> + <key>init_phase</key> + <value>16</value> + <type>real</type> + </param> + <param> + <name>Maximum Rate Deviation</name> + <key>max_dev</key> + <value>1.5</value> + <type>real</type> + </param> + <param> + <name>Output SPS</name> + <key>osps</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> + <source> + <name>err</name> + <type>float</type> + <optional>1</optional> + </source> + <source> + <name>rate</name> + <type>float</type> + <optional>1</optional> + </source> + <source> + <name>phase</name> + <type>float</type> + <optional>1</optional> + </source> +</block> diff --git a/gr-digital/grc/digital_pn_correlator_cc.xml b/gr-digital/grc/digital_pn_correlator_cc.xml new file mode 100644 index 000000000..999cea15d --- /dev/null +++ b/gr-digital/grc/digital_pn_correlator_cc.xml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<!-- +################################################### +##PN Correlator +################################################### + --> +<block> + <name>PN Correlator</name> + <key>digital_pn_correlator_cc</key> + <import>from gnuradio import digital</import> + <make>digital.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> + <value>0</value> + <type>int</type> + </param> + <param> + <name>Seed</name> + <key>seed</key> + <value>1</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-digital/grc/digital_probe_density_b.xml b/gr-digital/grc/digital_probe_density_b.xml new file mode 100644 index 000000000..8cf5dd894 --- /dev/null +++ b/gr-digital/grc/digital_probe_density_b.xml @@ -0,0 +1,29 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Probe Density +################################################### + --> +<block> + <name>Probe Density</name> + <key>digital_probe_density_b</key> + <import>from gnuradio import digital</import> + <make>digital.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> +</block> diff --git a/gr-digital/grc/digital_scrambler_bb.xml b/gr-digital/grc/digital_scrambler_bb.xml new file mode 100644 index 000000000..9c40b49f6 --- /dev/null +++ b/gr-digital/grc/digital_scrambler_bb.xml @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Descrambler +################################################### + --> +<block> + <name>Scrambler</name> + <key>digital_scrambler_bb</key> + <import>from gnuradio import digital</import> + <make>digital.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/gr-digital/grc/digital_simple_framer.xml b/gr-digital/grc/digital_simple_framer.xml new file mode 100644 index 000000000..bbeed32d3 --- /dev/null +++ b/gr-digital/grc/digital_simple_framer.xml @@ -0,0 +1,25 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Simple Framer +################################################### + --> +<block> + <name>Simple Framer</name> + <key>digital_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/gr-digital/include/CMakeLists.txt b/gr-digital/include/CMakeLists.txt index 81ed8d368..f863b2875 100644 --- a/gr-digital/include/CMakeLists.txt +++ b/gr-digital/include/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 # @@ -17,25 +17,94 @@ # 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_dict(name, sig, 'digital') + 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(digital_chunks_to_symbols_XX bf bc sf sc if ic) + +add_custom_target(digital_generated_includes DEPENDS + ${generated_includes} +) + ######################################################################## # Install header files ######################################################################## install(FILES + ${generated_includes} digital_api.h + digital_impl_glfsr.h digital_impl_mpsk_snr_est.h + digital_additive_scrambler_bb.h digital_binary_slicer_fb.h + digital_bytes_to_syms.h digital_clock_recovery_mm_cc.h digital_clock_recovery_mm_ff.h + digital_cma_equalizer_cc.h + digital_cpmmod_bc.h digital_constellation.h digital_constellation_receiver_cb.h digital_constellation_decoder_cb.h digital_correlate_access_code_bb.h + digital_correlate_access_code_tag_bb.h digital_costas_loop_cc.h - digital_cma_equalizer_cc.h digital_crc32.h + digital_descrambler_bb.h + digital_diff_decoder_bb.h + digital_diff_encoder_bb.h + digital_diff_phasor_cc.h + digital_framer_sink_1.h digital_fll_band_edge_cc.h + digital_glfsr_source_b.h + digital_glfsr_source_f.h + digital_gmskmod_bc.h digital_lms_dd_equalizer_cc.h digital_kurtotic_equalizer_cc.h + digital_map_bb.h digital_metric_type.h digital_mpsk_receiver_cc.h digital_mpsk_snr_est_cc.h @@ -45,9 +114,16 @@ install(FILES digital_ofdm_insert_preamble.h digital_ofdm_mapper_bcv.h digital_ofdm_sampler.h + digital_packet_sink.h + digital_pfb_clock_sync_ccf.h + digital_pfb_clock_sync_fff.h + digital_pn_correlator_cc.h + digital_probe_density_b.h digital_probe_mpsk_snr_est_c.h - digital_gmskmod_bc.h - digital_cpmmod_bc.h + digital_scrambler_bb.h + digital_simple_framer.h + digital_simple_framer_sync.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "digital_devel" ) + diff --git a/gr-digital/include/digital_additive_scrambler_bb.h b/gr-digital/include/digital_additive_scrambler_bb.h new file mode 100644 index 000000000..d4bd7d4ae --- /dev/null +++ b/gr-digital/include/digital_additive_scrambler_bb.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * 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 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 <digital_api.h> +#include <gr_sync_block.h> +#include <gri_lfsr.h> + +class digital_additive_scrambler_bb; +typedef boost::shared_ptr<digital_additive_scrambler_bb> digital_additive_scrambler_bb_sptr; + +DIGITAL_API digital_additive_scrambler_bb_sptr +digital_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 DIGITAL_API digital_additive_scrambler_bb : public gr_sync_block +{ + friend DIGITAL_API digital_additive_scrambler_bb_sptr + digital_make_additive_scrambler_bb(int mask, int seed, + int len, int count); + + gri_lfsr d_lfsr; + int d_count; + int d_bits; + + digital_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/gr-digital/include/digital_bytes_to_syms.h b/gr-digital/include/digital_bytes_to_syms.h new file mode 100644 index 000000000..3062366b9 --- /dev/null +++ b/gr-digital/include/digital_bytes_to_syms.h @@ -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. + */ +#ifndef INCLUDED_GR_BYTES_TO_SYMS_H +#define INCLUDED_GR_BYTES_TO_SYMS_H + +#include <digital_api.h> +#include <gr_sync_interpolator.h> + +class digital_bytes_to_syms; +typedef boost::shared_ptr<digital_bytes_to_syms> digital_bytes_to_syms_sptr; + +DIGITAL_API digital_bytes_to_syms_sptr digital_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 DIGITAL_API digital_bytes_to_syms : public gr_sync_interpolator +{ + friend DIGITAL_API digital_bytes_to_syms_sptr + digital_make_bytes_to_syms(); + + digital_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/gr-digital/include/digital_chunks_to_symbols_XX.h.t b/gr-digital/include/digital_chunks_to_symbols_XX.h.t new file mode 100644 index 000000000..92b7c94d5 --- /dev/null +++ b/gr-digital/include/digital_chunks_to_symbols_XX.h.t @@ -0,0 +1,75 @@ +/* -*- 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 <digital_api.h> +#include <gr_sync_interpolator.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +DIGITAL_API @SPTR_NAME@ +digital_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 constellation points in D dimensions (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 digital_chunks_to_symbols_bf, digital_chunks_to_symbols_bc. + * \sa digital_chunks_to_symbols_sf, digital_chunks_to_symbols_sc. + */ + +class DIGITAL_API @NAME@ : public gr_sync_interpolator +{ + friend DIGITAL_API @SPTR_NAME@ digital_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/gr-digital/include/digital_cma_equalizer_cc.h b/gr-digital/include/digital_cma_equalizer_cc.h index 0d703789a..79e84ca4b 100644 --- a/gr-digital/include/digital_cma_equalizer_cc.h +++ b/gr-digital/include/digital_cma_equalizer_cc.h @@ -41,9 +41,9 @@ digital_make_cma_equalizer_cc(int num_taps, float modulus, float mu, int sps); * * The error value and tap update equations (for p=2) can be found in: * - * D. Godard, "Self-Recovering Equalization and Carrier Tracking in + * "D. Godard, "Self-Recovering Equalization and Carrier Tracking in * Two-Dimensional Data Communication Systems," IEEE Transactions on - * Communications, Vol. 28, No. 11, pp. 1867 - 1875, 1980, + * Communications, Vol. 28, No. 11, pp. 1867 - 1875, 1980." */ class DIGITAL_API digital_cma_equalizer_cc : public gr_adaptive_fir_ccc { diff --git a/gr-digital/include/digital_constellation_receiver_cb.h b/gr-digital/include/digital_constellation_receiver_cb.h index 8547bdd68..3a14bb5de 100644 --- a/gr-digital/include/digital_constellation_receiver_cb.h +++ b/gr-digital/include/digital_constellation_receiver_cb.h @@ -60,9 +60,9 @@ digital_make_constellation_receiver_cb (digital_constellation_sptr constellation * The symbol synchronization is done using a modified Mueller and * Muller circuit from the paper: * - * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller - * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22 - * June 1995, pp. 1032 - 1033. + * "G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller + * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22 + * June 1995, pp. 1032 - 1033." * * This circuit interpolates the downconverted sample (using the NCO * developed by the Costas loop) every mu samples, then it finds the diff --git a/gr-digital/include/digital_correlate_access_code_tag_bb.h b/gr-digital/include/digital_correlate_access_code_tag_bb.h new file mode 100644 index 000000000..b4a12108f --- /dev/null +++ b/gr-digital/include/digital_correlate_access_code_tag_bb.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006,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_digital_correlate_access_code_tag_bb_H +#define INCLUDED_digital_correlate_access_code_tag_bb_H + +#include <digital_api.h> +#include <gr_sync_block.h> +#include <string> + +class digital_correlate_access_code_tag_bb; +typedef boost::shared_ptr<digital_correlate_access_code_tag_bb> digital_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 + */ +DIGITAL_API digital_correlate_access_code_tag_bb_sptr +digital_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 DIGITAL_API digital_correlate_access_code_tag_bb : public gr_sync_block +{ + friend DIGITAL_API digital_correlate_access_code_tag_bb_sptr + digital_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: + digital_correlate_access_code_tag_bb(const std::string &access_code, + int threshold, + const std::string &tag_name); + + public: + ~digital_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_digital_correlate_access_code_tag_bb_H */ diff --git a/gr-digital/include/digital_cpmmod_bc.h b/gr-digital/include/digital_cpmmod_bc.h index 332856afc..f0f11ee30 100644 --- a/gr-digital/include/digital_cpmmod_bc.h +++ b/gr-digital/include/digital_cpmmod_bc.h @@ -74,9 +74,10 @@ digital_make_cpmmod_bc(int type, float h, */ class DIGITAL_API digital_cpmmod_bc : public gr_hier_block2 { - friend DIGITAL_API digital_cpmmod_bc_sptr digital_make_cpmmod_bc(int type, float h, - unsigned samples_per_sym, - unsigned L, double beta); + friend DIGITAL_API digital_cpmmod_bc_sptr + digital_make_cpmmod_bc(int type, float h, + unsigned samples_per_sym, + unsigned L, double beta); std::vector<float> d_taps; gr_char_to_float_sptr d_char_to_float; diff --git a/gr-digital/include/digital_descrambler_bb.h b/gr-digital/include/digital_descrambler_bb.h new file mode 100644 index 000000000..b719803f3 --- /dev/null +++ b/gr-digital/include/digital_descrambler_bb.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 INCLUDED_GR_DESCRAMBLER_BB_H +#define INCLUDED_GR_DESCRAMBLER_BB_H + +#include <digital_api.h> +#include <gr_sync_block.h> +#include "gri_lfsr.h" + +class digital_descrambler_bb; +typedef boost::shared_ptr<digital_descrambler_bb> digital_descrambler_bb_sptr; + +DIGITAL_API digital_descrambler_bb_sptr +digital_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 DIGITAL_API digital_descrambler_bb : public gr_sync_block +{ + friend DIGITAL_API digital_descrambler_bb_sptr + digital_make_descrambler_bb(int mask, int seed, int len); + + gri_lfsr d_lfsr; + + digital_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/gr-digital/include/digital_diff_decoder_bb.h b/gr-digital/include/digital_diff_decoder_bb.h new file mode 100644 index 000000000..928035d0e --- /dev/null +++ b/gr-digital/include/digital_diff_decoder_bb.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_DIFF_DECODER_BB_H +#define INCLUDED_GR_DIFF_DECODER_BB_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +class digital_diff_decoder_bb; +typedef boost::shared_ptr<digital_diff_decoder_bb> digital_diff_decoder_bb_sptr; + +DIGITAL_API digital_diff_decoder_bb_sptr +digital_make_diff_decoder_bb(unsigned int modulus); + +/*! + * \brief y[0] = (x[0] - x[-1]) % M + * \ingroup coding_blk + * + * Uses current and previous symbols and the alphabet modulus to + * perform differential decoding. + */ +class DIGITAL_API digital_diff_decoder_bb : public gr_sync_block +{ + friend DIGITAL_API digital_diff_decoder_bb_sptr + digital_make_diff_decoder_bb(unsigned int modulus); + digital_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/gr-digital/include/digital_diff_encoder_bb.h b/gr-digital/include/digital_diff_encoder_bb.h new file mode 100644 index 000000000..d4be69cad --- /dev/null +++ b/gr-digital/include/digital_diff_encoder_bb.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_DIFF_ENCODER_BB_H +#define INCLUDED_GR_DIFF_ENCODER_BB_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +class digital_diff_encoder_bb; +typedef boost::shared_ptr<digital_diff_encoder_bb> digital_diff_encoder_bb_sptr; + +DIGITAL_API digital_diff_encoder_bb_sptr +digital_make_diff_encoder_bb(unsigned int modulus); + +/*! + * \brief y[0] = (x[0] + y[-1]) % M + * \ingroup coding_blk + * + * Uses current and previous symbols and the alphabet modulus to + * perform differential encoding. + */ +class DIGITAL_API digital_diff_encoder_bb : public gr_sync_block +{ + friend DIGITAL_API digital_diff_encoder_bb_sptr + digital_make_diff_encoder_bb(unsigned int modulus); + digital_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/gr-digital/include/digital_diff_phasor_cc.h b/gr-digital/include/digital_diff_phasor_cc.h new file mode 100644 index 000000000..32a2464b2 --- /dev/null +++ b/gr-digital/include/digital_diff_phasor_cc.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_DIFF_PHASOR_CC_H +#define INCLUDED_GR_DIFF_PHASOR_CC_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +/*! + * \brief Differential decoding based on phase change. + * \ingroup coding_blk + * + * Uses the phase difference between two symbols to determine the + * output symbol: + * + * out[i] = in[i] * conj(in[i-1]); + */ +class digital_diff_phasor_cc; +typedef boost::shared_ptr<digital_diff_phasor_cc> digital_diff_phasor_cc_sptr; + +DIGITAL_API digital_diff_phasor_cc_sptr digital_make_diff_phasor_cc(); + + +class DIGITAL_API digital_diff_phasor_cc : public gr_sync_block +{ + friend DIGITAL_API digital_diff_phasor_cc_sptr + digital_make_diff_phasor_cc(); + + digital_diff_phasor_cc(); //constructor + + public: + ~digital_diff_phasor_cc(); //destructor + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gr-digital/include/digital_fll_band_edge_cc.h b/gr-digital/include/digital_fll_band_edge_cc.h index f07d7ba42..c70bfc86d 100644 --- a/gr-digital/include/digital_fll_band_edge_cc.h +++ b/gr-digital/include/digital_fll_band_edge_cc.h @@ -65,8 +65,8 @@ DIGITAL_API digital_fll_band_edge_cc_sptr digital_make_fll_band_edge_cc (float s * abs(x_l(t))^2 - abs(x_u(t))^2 = norm(x_l(t)) - norm(x_u(t)). * * In theory, the band-edge filter is the derivative of the matched - * filter in frequency, (H_be(f) = \\frac{H(f)}{df}. In practice, this - * comes down to a quarter sine wave at the point of the matched + * filter in frequency, (H_be(f) = frac{H(f)}{df}). In practice, + * this comes down to a quarter sine wave at the point of the matched * filter's rolloff (if it's a raised-cosine, the derivative of a * cosine is a sine). Extend this sine by another quarter wave to * make a half wave around the band-edges is equivalent in time to the diff --git a/gr-digital/include/digital_framer_sink_1.h b/gr-digital/include/digital_framer_sink_1.h new file mode 100644 index 000000000..bb82bf5a7 --- /dev/null +++ b/gr-digital/include/digital_framer_sink_1.h @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_GR_FRAMER_SINK_1_H +#define INCLUDED_GR_FRAMER_SINK_1_H + +#include <digital_api.h> +#include <gr_sync_block.h> +#include <gr_msg_queue.h> + +class digital_framer_sink_1; +typedef boost::shared_ptr<digital_framer_sink_1> digital_framer_sink_1_sptr; + +DIGITAL_API digital_framer_sink_1_sptr +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 + * 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 DIGITAL_API digital_framer_sink_1 : public gr_sync_block +{ + friend DIGITAL_API digital_framer_sink_1_sptr + digital_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: + digital_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: + ~digital_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/gr-digital/include/digital_glfsr_source_b.h b/gr-digital/include/digital_glfsr_source_b.h new file mode 100644 index 000000000..92e5e81f5 --- /dev/null +++ b/gr-digital/include/digital_glfsr_source_b.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_GLFSR_SOURCE_B_H +#define INCLUDED_GR_GLFSR_SOURCE_B_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +class gri_glfsr; + +class digital_glfsr_source_b; +typedef boost::shared_ptr<digital_glfsr_source_b> digital_glfsr_source_b_sptr; + +DIGITAL_API digital_glfsr_source_b_sptr +digital_make_glfsr_source_b(int degree, bool repeat=true, + int mask=0, int seed=1); + +/*! + * \brief Galois LFSR pseudo-random source + * \ingroup source_blk + * + * \param degree Degree of shift register must be in [1, 32]. If mask + * is 0, the degree determines a default mask (see + * digital_impl_glfsr.cc for the mapping). + * \param repeat Set to repeat sequence. + * \param mask Allows a user-defined bit mask for indexes of the shift + * register to feed back. + * \param seed Initial setting for values in shift register. + */ +class DIGITAL_API digital_glfsr_source_b : public gr_sync_block +{ + private: + friend DIGITAL_API digital_glfsr_source_b_sptr + digital_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; + + digital_glfsr_source_b(int degree, bool repeat, + int mask, int seed); + + public: + + ~digital_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/gr-digital/include/digital_glfsr_source_f.h b/gr-digital/include/digital_glfsr_source_f.h new file mode 100644 index 000000000..77d7b0f74 --- /dev/null +++ b/gr-digital/include/digital_glfsr_source_f.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_GLFSR_SOURCE_F_H +#define INCLUDED_GR_GLFSR_SOURCE_F_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +class gri_glfsr; + +class digital_glfsr_source_f; +typedef boost::shared_ptr<digital_glfsr_source_f> digital_glfsr_source_f_sptr; + +DIGITAL_API digital_glfsr_source_f_sptr +digital_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 + * + * \param degree Degree of shift register must be in [1, 32]. If mask + * is 0, the degree determines a default mask (see + * digital_impl_glfsr.cc for the mapping). + * \param repeat Set to repeat sequence. + * \param mask Allows a user-defined bit mask for indexes of the shift + * register to feed back. + * \param seed Initial setting for values in shift register. + */ +class DIGITAL_API digital_glfsr_source_f : public gr_sync_block +{ + private: + friend DIGITAL_API digital_glfsr_source_f_sptr + digital_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; + + digital_glfsr_source_f(int degree, bool repeat, + int mask, int seed); + + public: + + ~digital_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/gr-digital/include/digital_impl_glfsr.h b/gr-digital/include/digital_impl_glfsr.h new file mode 100644 index 000000000..3aadf7cf2 --- /dev/null +++ b/gr-digital/include/digital_impl_glfsr.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_DIGITAL_IMPL_GLFSR_H +#define INCLUDED_DIGITAL_IMPL_GLFSR_H + +#include <digital_api.h> + +/*! + * \brief Galois Linear Feedback Shift Register using specified polynomial mask + * \ingroup misc + * + * Generates a maximal length pseudo-random sequence of length 2^degree-1 + */ + +class DIGITAL_API digital_impl_glfsr +{ + private: + int d_shift_register; + int d_mask; + + public: + + digital_impl_glfsr(int mask, int seed) { d_shift_register = seed; d_mask = mask; } + static int glfsr_mask(int degree); + + unsigned char next_bit() { + unsigned char bit = d_shift_register & 1; + d_shift_register >>= 1; + if (bit) + d_shift_register ^= d_mask; + return bit; + } + + int mask() const { return d_mask; } +}; + +#endif /* INCLUDED_DIGITAL_IMPL_GLFSR_H */ diff --git a/gr-digital/include/digital_kurtotic_equalizer_cc.h b/gr-digital/include/digital_kurtotic_equalizer_cc.h index 3ac8712d5..fed88c374 100644 --- a/gr-digital/include/digital_kurtotic_equalizer_cc.h +++ b/gr-digital/include/digital_kurtotic_equalizer_cc.h @@ -39,9 +39,9 @@ digital_make_kurtotic_equalizer_cc(int num_taps, float mu); * \ingroup eq_blk * \ingroup digital * - * Y. Guo, J. Zhao, Y. Sun, "Sign kurtosis maximization based blind + * "Y. Guo, J. Zhao, Y. Sun, "Sign kurtosis maximization based blind * equalization algorithm," IEEE Conf. on Control, Automation, - * Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057. + * Robotics and Vision, Vol. 3, Dec. 2004, pp. 2052 - 2057." */ class DIGITAL_API digital_kurtotic_equalizer_cc : public gr_adaptive_fir_ccc { diff --git a/gr-digital/include/digital_map_bb.h b/gr-digital/include/digital_map_bb.h new file mode 100644 index 000000000..4aca66fbe --- /dev/null +++ b/gr-digital/include/digital_map_bb.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_MAP_BB_H +#define INCLUDED_GR_MAP_BB_H + +#include <digital_api.h> +#include <gr_sync_block.h> + +class digital_map_bb; +typedef boost::shared_ptr<digital_map_bb> digital_map_bb_sptr; + +DIGITAL_API digital_map_bb_sptr +digital_make_map_bb(const std::vector<int> &map); + +/*! + * \brief output[i] = map[input[i]] + * \ingroup coding_blk + * + * This block maps an incoming signal to the value in the map. + * The block expects that the incoming signal has a maximum + * value of len(map)-1. + * + * -> output[i] = map[input[i]] + * + * \param map a vector of integers. + */ + +class DIGITAL_API digital_map_bb : public gr_sync_block +{ + friend DIGITAL_API digital_map_bb_sptr + digital_make_map_bb(const std::vector<int> &map); + + unsigned char d_map[0x100]; + + digital_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 */ diff --git a/gr-digital/include/digital_mpsk_receiver_cc.h b/gr-digital/include/digital_mpsk_receiver_cc.h index 02cea8d25..1f11a26b6 100644 --- a/gr-digital/include/digital_mpsk_receiver_cc.h +++ b/gr-digital/include/digital_mpsk_receiver_cc.h @@ -65,10 +65,10 @@ digital_make_mpsk_receiver_cc (unsigned int M, float theta, * * The symbol synchronization is done using a modified Mueller and * Muller circuit from the paper: - * - * G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller - * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22 - * June 1995, pp. 1032 - 1033. + * + * "G. R. Danesfahani, T. G. Jeans, "Optimisation of modified Mueller + * and Muller algorithm," Electronics Letters, Vol. 31, no. 13, 22 + * June 1995, pp. 1032 - 1033." * * This circuit interpolates the downconverted sample (using the NCO * developed by the Costas loop) every mu samples, then it finds the diff --git a/gr-digital/include/digital_packet_sink.h b/gr-digital/include/digital_packet_sink.h new file mode 100644 index 000000000..7ab41c0ef --- /dev/null +++ b/gr-digital/include/digital_packet_sink.h @@ -0,0 +1,131 @@ +/* -*- 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_GR_PACKET_SINK_H +#define INCLUDED_GR_PACKET_SINK_H + +#include <digital_api.h> +#include <gr_sync_block.h> +#include <gr_msg_queue.h> + +class digital_packet_sink; +typedef boost::shared_ptr<digital_packet_sink> digital_packet_sink_sptr; + +DIGITAL_API digital_packet_sink_sptr +digital_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 + * + * input: stream of symbols to be sliced. + * + * output: none. Pushes assembled packet into target queue + * + * The packet sink takes in a stream of binary symbols that are sliced + * around 0. The bits are then checked for the \p sync_vector to + * determine find and decode the packet. It then 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. + * + * This block is not very useful anymore as it only works with 2-level + * modulations such as BPSK or GMSK. The block can generally be + * replaced with a correlate access code and frame sink blocks. + * + * \param sync_vector The synchronization vector as a vector of 1's and 0's. + * \param target_queue The message queue that packets are sent to. + * \param threshold Number of bits that can be incorrect in the \p sync_vector. + */ +class DIGITAL_API digital_packet_sink : public gr_sync_block +{ + friend DIGITAL_API digital_packet_sink_sptr + digital_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: + digital_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: + ~digital_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/gr-digital/include/digital_pfb_clock_sync_ccf.h b/gr-digital/include/digital_pfb_clock_sync_ccf.h new file mode 100644 index 000000000..1b403ab25 --- /dev/null +++ b/gr-digital/include/digital_pfb_clock_sync_ccf.h @@ -0,0 +1,376 @@ +/* -*- 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_DIGITAL_PFB_CLOCK_SYNC_CCF_H +#define INCLUDED_DIGITAL_PFB_CLOCK_SYNC_CCF_H + +#include <digital_api.h> +#include <gr_block.h> + +class digital_pfb_clock_sync_ccf; +typedef boost::shared_ptr<digital_pfb_clock_sync_ccf> digital_pfb_clock_sync_ccf_sptr; +DIGITAL_API digital_pfb_clock_sync_ccf_sptr +digital_make_pfb_clock_sync_ccf(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5, + int osps=1); + +class gr_fir_ccf; + +/*! + * \class digital_pfb_clock_sync_ccf + * + * \brief Timing synchronizer using polyphase filterbanks + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. + * + * This approach works by setting up two filterbanks; one filterbank + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. + * + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. + * + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. + * + * The block's parameters are: + * + * \li \p sps: The clock sync block needs to know the number of samples per + * symbol, because it defaults to return a single point representing + * the symbol. The sps can be any positive real number and does not + * need to be an integer. + * + * \li \p loop_bw: The loop bandwidth is used to set the gain of the + * inner control loop (see: + * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). + * This should be set small (a value of around 2pi/100 is suggested in + * that blog post as the step size for the number of radians around + * the unit circle to move relative to the error). + * + * \li \p taps: One of the most important parameters for this block is + * the taps of the filter. One of the benefits of this algorithm is + * that you can put the matched filter in here as the taps, so you get + * both the matched filter and sample timing correction in one go. So + * create your normal matched filter. For a typical digital + * modulation, this is a root raised cosine filter. The number of taps + * of this filter is based on how long you expect the channel to be; + * that is, how many symbols do you want to combine to get the current + * symbols energy back (there's probably a better way of stating + * that). It's usually 5 to 10 or so. That gives you your filter, but + * now we need to think about it as a filter with different phase + * profiles in each filter. So take this number of taps and multiply + * it by the number of filters. This is the number you would use to + * create your prototype filter. When you use this in the PFB + * filerbank, it segments these taps into the filterbanks in such a + * way that each bank now represents the filter at different phases, + * equally spaced at 2pi/N, where N is the number of filters. + * + * \li \p filter_size (default=32): The number of filters can also be + * set and defaults to 32. With 32 filters, you get a good enough + * resolution in the phase to produce very small, almost unnoticeable, + * ISI. Going to 64 filters can reduce this more, but after that + * there is very little gained for the extra complexity. + * + * \li \p init_phase (default=0): The initial phase is another + * settable parameter and refers to the filter path the algorithm + * initially looks at (i.e., d_k starts at init_phase). This value + * defaults to zero, but it might be useful to start at a different + * phase offset, such as the mid-point of the filters. + * + * \li \p max_rate_deviation (default=1.5): The next parameter is the + * max_rate_devitation, which defaults to 1.5. This is how far we + * allow d_rate to swing, positive or negative, from 0. Constraining + * the rate can help keep the algorithm from walking too far away to + * lock during times when there is no signal. + * + * \li \p osps (default=1): The osps is the number of output samples per symbol. By default, + * the algorithm produces 1 sample per symbol, sampled at the exact + * sample value. This osps value was added to better work with + * equalizers, which do a better job of modeling the channel if they + * have 2 samps/sym. + */ + +class DIGITAL_API digital_pfb_clock_sync_ccf : public gr_block +{ + private: + /*! + * Build the polyphase filterbank timing synchronizer. + * \param sps (double) The number of samples per symbol in the incoming signal + * \param loop_bw (float) The bandwidth of the control loop; set's alpha and beta. + * \param taps (vector<int>) The filter taps. + * \param filter_size (uint) The number of filters in the filterbank (default = 32). + * \param init_phase (float) The initial phase to look at, or which filter to start + * with (default = 0). + * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). + * \param osps (int) The number of output samples per symbol (default=1). + * + */ + friend DIGITAL_API digital_pfb_clock_sync_ccf_sptr + digital_make_pfb_clock_sync_ccf(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + bool d_updated; + double d_sps; + double d_sample_num; + float d_loop_bw; + float d_damping; + float d_alpha; + float d_beta; + + int d_nfilters; + int d_taps_per_filter; + std::vector<gr_fir_ccf*> d_filters; + std::vector<gr_fir_ccf*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + + float d_k; + float d_rate; + float d_rate_i; + float d_rate_f; + float d_max_dev; + int d_filtnum; + int d_osps; + float d_error; + int d_out_idx; + + /*! + * Build the polyphase filterbank timing synchronizer. + */ + digital_pfb_clock_sync_ccf(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + +public: + ~digital_pfb_clock_sync_ccf(); + + /*! \brief update the system gains from omega and eta + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + */ + void set_taps(const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter); + + /*! + * Returns all of the taps of the matched filter + */ + std::vector< std::vector<float> > get_taps(); + + /*! + * Returns all of the taps of the derivative filter + */ + std::vector< std::vector<float> > get_diff_taps(); + + /*! + * Returns the taps of the matched filter for a particular channel + */ + std::vector<float> get_channel_taps(int channel); + + /*! + * Returns the taps in the derivative filter for a particular channel + */ + std::vector<float> get_diff_channel_taps(int channel); + + /*! + * Return the taps as a formatted string for printing + */ + std::string get_taps_as_string(); + + /*! + * Return the derivative filter taps as a formatted string for printing + */ + std::string get_diff_taps_as_string(); + + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); + + /*! + * Set the maximum deviation from 0 d_rate can have + */ + void set_max_rate_deviation(float m) + { + d_max_dev = m; + } + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Returns the current clock rate + */ + float get_clock_rate() const; + + /******************************************************************* + *******************************************************************/ + + bool check_topology(int ninputs, int noutputs); + + 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 diff --git a/gr-digital/include/digital_pfb_clock_sync_fff.h b/gr-digital/include/digital_pfb_clock_sync_fff.h new file mode 100644 index 000000000..c7e8babd6 --- /dev/null +++ b/gr-digital/include/digital_pfb_clock_sync_fff.h @@ -0,0 +1,376 @@ +/* -*- 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_DIGITAL_PFB_CLOCK_SYNC_FFF_H +#define INCLUDED_DIGITAL_PFB_CLOCK_SYNC_FFF_H + +#include <digital_api.h> +#include <gr_block.h> + +class digital_pfb_clock_sync_fff; +typedef boost::shared_ptr<digital_pfb_clock_sync_fff> digital_pfb_clock_sync_fff_sptr; +DIGITAL_API digital_pfb_clock_sync_fff_sptr +digital_make_pfb_clock_sync_fff(double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5, + int osps=1); + +class gr_fir_fff; + +/*! + * \class digital_pfb_clock_sync_fff + * + * \brief Timing synchronizer using polyphase filterbanks + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. + * + * This approach works by setting up two filterbanks; one filterbank + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. + * + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. + * + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. + * + * The block's parameters are: + * + * \li \p sps: The clock sync block needs to know the number of samples per + * symbol, because it defaults to return a single point representing + * the symbol. The sps can be any positive real number and does not + * need to be an integer. + * + * \li \p loop_bw: The loop bandwidth is used to set the gain of the + * inner control loop (see: + * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). + * This should be set small (a value of around 2pi/100 is suggested in + * that blog post as the step size for the number of radians around + * the unit circle to move relative to the error). + * + * \li \p taps: One of the most important parameters for this block is + * the taps of the filter. One of the benefits of this algorithm is + * that you can put the matched filter in here as the taps, so you get + * both the matched filter and sample timing correction in one go. So + * create your normal matched filter. For a typical digital + * modulation, this is a root raised cosine filter. The number of taps + * of this filter is based on how long you expect the channel to be; + * that is, how many symbols do you want to combine to get the current + * symbols energy back (there's probably a better way of stating + * that). It's usually 5 to 10 or so. That gives you your filter, but + * now we need to think about it as a filter with different phase + * profiles in each filter. So take this number of taps and multiply + * it by the number of filters. This is the number you would use to + * create your prototype filter. When you use this in the PFB + * filerbank, it segments these taps into the filterbanks in such a + * way that each bank now represents the filter at different phases, + * equally spaced at 2pi/N, where N is the number of filters. + * + * \li \p filter_size (default=32): The number of filters can also be + * set and defaults to 32. With 32 filters, you get a good enough + * resolution in the phase to produce very small, almost unnoticeable, + * ISI. Going to 64 filters can reduce this more, but after that + * there is very little gained for the extra complexity. + * + * \li \p init_phase (default=0): The initial phase is another + * settable parameter and refers to the filter path the algorithm + * initially looks at (i.e., d_k starts at init_phase). This value + * defaults to zero, but it might be useful to start at a different + * phase offset, such as the mid-point of the filters. + * + * \li \p max_rate_deviation (default=1.5): The next parameter is the + * max_rate_devitation, which defaults to 1.5. This is how far we + * allow d_rate to swing, positive or negative, from 0. Constraining + * the rate can help keep the algorithm from walking too far away to + * lock during times when there is no signal. + * + * \li \p osps (default=1): The osps is the number of output samples + * per symbol. By default, the algorithm produces 1 sample per symbol, + * sampled at the exact sample value. This osps value was added to + * better work with equalizers, which do a better job of modeling the + * channel if they have 2 samps/sym. + */ + +class DIGITAL_API digital_pfb_clock_sync_fff : public gr_block +{ + private: + /*! + * Build the polyphase filterbank timing synchronizer. + * \param sps (double) The number of samples per second in the incoming signal + * \param gain (float) The alpha gain of the control loop; beta = (gain^2)/4 by default. + * \param taps (vector<int>) The filter taps. + * \param filter_size (uint) The number of filters in the filterbank (default = 32). + * \param init_phase (float) The initial phase to look at, or which filter to start + * with (default = 0). + * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). + * \param osps (int) The number of output samples per symbol (default=1). + * + */ + friend DIGITAL_API digital_pfb_clock_sync_fff_sptr + digital_make_pfb_clock_sync_fff(double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + bool d_updated; + double d_sps; + double d_sample_num; + float d_loop_bw; + float d_damping; + float d_alpha; + float d_beta; + + int d_nfilters; + int d_taps_per_filter; + std::vector<gr_fir_fff*> d_filters; + std::vector<gr_fir_fff*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + + float d_k; + float d_rate; + float d_rate_i; + float d_rate_f; + float d_max_dev; + int d_filtnum; + int d_osps; + float d_error; + int d_out_idx; + + /*! + * Build the polyphase filterbank timing synchronizer. + */ + digital_pfb_clock_sync_fff(double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + +public: + ~digital_pfb_clock_sync_fff (); + + /*! \brief update the system gains from omega and eta + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + */ + void set_taps(const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + /*! + * Returns all of the taps of the matched filter + */ + std::vector< std::vector<float> > get_taps(); + + /*! + * Returns all of the taps of the derivative filter + */ + std::vector< std::vector<float> > get_diff_taps(); + + /*! + * Returns the taps of the matched filter for a particular channel + */ + std::vector<float> get_channel_taps(int channel); + + /*! + * Returns the taps in the derivative filter for a particular channel + */ + std::vector<float> get_diff_channel_taps(int channel); + + /*! + * Return the taps as a formatted string for printing + */ + std::string get_taps_as_string(); + + /*! + * Return the derivative filter taps as a formatted string for printing + */ + std::string get_diff_taps_as_string(); + + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); + + /*! + * Set the maximum deviation from 0 d_rate can have + */ + void set_max_rate_deviation(float m) + { + d_max_dev = m; + } + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Returns the current clock rate + */ + float get_clock_rate() const; + + /******************************************************************* + *******************************************************************/ + + bool check_topology(int ninputs, int noutputs); + + 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 diff --git a/gr-digital/include/digital_pn_correlator_cc.h b/gr-digital/include/digital_pn_correlator_cc.h new file mode 100644 index 000000000..87cc2ff93 --- /dev/null +++ b/gr-digital/include/digital_pn_correlator_cc.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_PN_CORRELATOR_CC_H +#define INCLUDED_GR_PN_CORRELATOR_CC_H + +#include <digital_api.h> +#include <gr_sync_decimator.h> +#include <gri_glfsr.h> + +class digital_pn_correlator_cc; +typedef boost::shared_ptr<digital_pn_correlator_cc> digital_pn_correlator_cc_sptr; + +DIGITAL_API digital_pn_correlator_cc_sptr +digital_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. The PN + * sequence is generated using a GLFSR. + * + * \param degree Degree of shift register must be in [1, 32]. If mask + * is 0, the degree determines a default mask (see + * digital_impl_glfsr.cc for the mapping). + * \param repeat Set to repeat sequence. + * \param mask Allows a user-defined bit mask for indexes of the shift + * register to feed back. + * \param seed Initial setting for values in shift register. + */ +class DIGITAL_API digital_pn_correlator_cc : public gr_sync_decimator +{ + friend DIGITAL_API digital_pn_correlator_cc_sptr + digital_make_pn_correlator_cc(int degree, int mask, int seed); + + int d_len; + float d_pn; + gri_glfsr *d_reference; + + protected: + digital_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); + + ~digital_pn_correlator_cc(); +}; + +#endif /* INCLUDED_GR_PN_CORRELATOR_CC_H */ diff --git a/gr-digital/include/digital_probe_density_b.h b/gr-digital/include/digital_probe_density_b.h new file mode 100644 index 000000000..271ad2a07 --- /dev/null +++ b/gr-digital/include/digital_probe_density_b.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2012 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 <digital_api.h> +#include <gr_sync_block.h> + +class digital_probe_density_b; + +typedef boost::shared_ptr<digital_probe_density_b> digital_probe_density_b_sptr; + +DIGITAL_API digital_probe_density_b_sptr +digital_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 DIGITAL_API digital_probe_density_b : public gr_sync_block +{ +private: + friend DIGITAL_API digital_probe_density_b_sptr + digital_make_probe_density_b(double alpha); + + double d_alpha; + double d_beta; + double d_density; + + digital_probe_density_b(double alpha); + +public: + ~digital_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/gr-digital/include/digital_scrambler_bb.h b/gr-digital/include/digital_scrambler_bb.h new file mode 100644 index 000000000..d6f08dcc8 --- /dev/null +++ b/gr-digital/include/digital_scrambler_bb.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 INCLUDED_GR_SCRAMBLER_BB_H +#define INCLUDED_GR_SCRAMBLER_BB_H + +#include <digital_api.h> +#include <gr_sync_block.h> +#include "gri_lfsr.h" + +class digital_scrambler_bb; +typedef boost::shared_ptr<digital_scrambler_bb> digital_scrambler_bb_sptr; + +DIGITAL_API digital_scrambler_bb_sptr +digital_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 DIGITAL_API digital_scrambler_bb : public gr_sync_block +{ + friend DIGITAL_API digital_scrambler_bb_sptr + digital_make_scrambler_bb(int mask, int seed, int len); + + gri_lfsr d_lfsr; + + digital_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/gr-digital/include/digital_simple_framer.h b/gr-digital/include/digital_simple_framer.h new file mode 100644 index 000000000..b622ae5dd --- /dev/null +++ b/gr-digital/include/digital_simple_framer.h @@ -0,0 +1,66 @@ +/* -*- 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_GR_SIMPLE_FRAMER_H +#define INCLUDED_GR_SIMPLE_FRAMER_H + +#include <digital_api.h> +#include <gr_block.h> + +class digital_simple_framer; +typedef boost::shared_ptr<digital_simple_framer> digital_simple_framer_sptr; + +DIGITAL_API digital_simple_framer_sptr digital_make_simple_framer(int payload_bytesize); + +/*! + * \brief add sync field, seq number and command field to payload + * \ingroup sync_blk + * + * Takes in enough samples to create a full output frame. The frame is + * prepended with the GRSF_SYNC (defind in + * digital_simple_framer_sync.h) and an 8-bit sequence number. + * + * \param payload_bytesize The size of the payload in bytes. + */ +class DIGITAL_API digital_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 DIGITAL_API digital_simple_framer_sptr + digital_make_simple_framer(int payload_bytesize); + digital_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/gr-digital/include/digital_simple_framer_sync.h b/gr-digital/include/digital_simple_framer_sync.h new file mode 100644 index 000000000..412003582 --- /dev/null +++ b/gr-digital/include/digital_simple_framer_sync.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_GR_SIMPLE_FRAMER_SYNC_H +#define INCLUDED_GR_SIMPLE_FRAMER_SYNC_H + +/*! + * \brief Here are a couple of maximum length sequences (m-sequences) + * that were generated by the the "mseq" matlab/octave code downloaded + * from: <a href="http://www.mathworks.com/matlabcentral/fileexchange/990">http://www.mathworks.com/matlabcentral/fileexchange/990</a> + * + * <pre> + * 31-bit m-sequence: + * 0110100100001010111011000111110 + * 0x690AEC76 (padded on right with a zero) + * + * 63-bit m-sequence: + * 101011001101110110100100111000101111001010001100001000001111110 + * 0xACDDA4E2F28C20FC (padded on right with a zero) + * </pre> + */ + +static const unsigned long long GRSF_SYNC = 0xacdda4e2f28c20fcULL; + +static const int GRSF_BITS_PER_BYTE = 8; +static const int GRSF_SYNC_OVERHEAD = sizeof(GRSF_SYNC); +static const int GRSF_PAYLOAD_OVERHEAD = 1; // 1 byte seqno +static const int GRSF_TAIL_PAD = 1; // one byte trailing padding +static const int GRSF_OVERHEAD = GRSF_SYNC_OVERHEAD + GRSF_PAYLOAD_OVERHEAD + GRSF_TAIL_PAD; + + +#endif /* INCLUDED_GR_SIMPLE_FRAMER_SYNC_H */ diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index 779972ff3..bd4f1a500 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/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,29 +23,102 @@ include_directories( ${GNURADIO_CORE_INCLUDE_DIRS} ${GR_DIGITAL_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR}/../include ) include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) + +######################################################################## +# 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_dict(name, sig, 'digital') + 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}/../include/${name}.h) + endforeach(sig) + + #create a command to generate the 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} + ) + + #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}) +endmacro(expand_cc) + +######################################################################## +# Invoke macro to generate various sources +######################################################################## +expand_cc(digital_chunks_to_symbols_XX bf bc sf sc if ic) + ######################################################################## # Setup library ######################################################################## list(APPEND gr_digital_sources + ${generated_sources} + digital_impl_glfsr.cc digital_impl_mpsk_snr_est.cc + digital_additive_scrambler_bb.cc digital_binary_slicer_fb.cc + digital_bytes_to_syms.cc digital_clock_recovery_mm_cc.cc digital_clock_recovery_mm_ff.cc + digital_cma_equalizer_cc.cc digital_constellation.cc digital_constellation_receiver_cb.cc digital_constellation_decoder_cb.cc digital_correlate_access_code_bb.cc + digital_correlate_access_code_tag_bb.cc digital_costas_loop_cc.cc - digital_cma_equalizer_cc.cc + digital_cpmmod_bc.cc digital_crc32.cc + digital_descrambler_bb.cc + digital_diff_decoder_bb.cc + digital_diff_encoder_bb.cc + digital_diff_phasor_cc.cc digital_fll_band_edge_cc.cc + digital_framer_sink_1.cc + digital_glfsr_source_b.cc + digital_glfsr_source_f.cc + digital_gmskmod_bc.cc digital_lms_dd_equalizer_cc.cc digital_kurtotic_equalizer_cc.cc + digital_map_bb.cc digital_mpsk_receiver_cc.cc digital_mpsk_snr_est_cc.cc digital_ofdm_cyclic_prefixer.cc @@ -54,9 +127,14 @@ list(APPEND gr_digital_sources digital_ofdm_insert_preamble.cc digital_ofdm_mapper_bcv.cc digital_ofdm_sampler.cc + digital_packet_sink.cc + digital_pfb_clock_sync_ccf.cc + digital_pfb_clock_sync_fff.cc + digital_pn_correlator_cc.cc + digital_probe_density_b.cc digital_probe_mpsk_snr_est_c.cc - digital_gmskmod_bc.cc - digital_cpmmod_bc.cc + digital_scrambler_bb.cc + digital_simple_framer.cc ) list(APPEND digital_libs @@ -67,3 +145,5 @@ list(APPEND digital_libs add_library(gnuradio-digital SHARED ${gr_digital_sources}) target_link_libraries(gnuradio-digital ${digital_libs}) GR_LIBRARY_FOO(gnuradio-digital RUNTIME_COMPONENT "digital_runtime" DEVEL_COMPONENT "digital_devel") + +add_dependencies(gnuradio-digital digital_generated_includes digital_generated_swigs) diff --git a/gr-digital/lib/digital_additive_scrambler_bb.cc b/gr-digital/lib/digital_additive_scrambler_bb.cc new file mode 100644 index 000000000..a8affaa78 --- /dev/null +++ b/gr-digital/lib/digital_additive_scrambler_bb.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * 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 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 <digital_additive_scrambler_bb.h> +#include <gr_io_signature.h> + +digital_additive_scrambler_bb_sptr +digital_make_additive_scrambler_bb(int mask, int seed, int len, int count) +{ + return gnuradio::get_initial_sptr(new digital_additive_scrambler_bb + (mask, seed, len, count)); +} + +digital_additive_scrambler_bb::digital_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 +digital_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/gr-digital/lib/digital_bytes_to_syms.cc b/gr-digital/lib/digital_bytes_to_syms.cc new file mode 100644 index 000000000..f8bd82d5b --- /dev/null +++ b/gr-digital/lib/digital_bytes_to_syms.cc @@ -0,0 +1,74 @@ +/* -*- 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 <digital_bytes_to_syms.h> +#include <gr_io_signature.h> +#include <assert.h> + +static const int BITS_PER_BYTE = 8; + +digital_bytes_to_syms_sptr +digital_make_bytes_to_syms () +{ + return gnuradio::get_initial_sptr(new digital_bytes_to_syms ()); +} + +digital_bytes_to_syms::digital_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 +digital_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/gr-digital/lib/digital_chunks_to_symbols_XX.cc.t b/gr-digital/lib/digital_chunks_to_symbols_XX.cc.t new file mode 100644 index 000000000..399a474a6 --- /dev/null +++ b/gr-digital/lib/digital_chunks_to_symbols_XX.cc.t @@ -0,0 +1,74 @@ +/* -*- 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 <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <iostream> +#include <string.h> + +@SPTR_NAME@ +digital_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/gr-digital/lib/digital_correlate_access_code_tag_bb.cc b/gr-digital/lib/digital_correlate_access_code_tag_bb.cc new file mode 100644 index 000000000..95f06534e --- /dev/null +++ b/gr-digital/lib/digital_correlate_access_code_tag_bb.cc @@ -0,0 +1,131 @@ +/* -*- 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 <digital_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 + + +digital_correlate_access_code_tag_bb_sptr +digital_make_correlate_access_code_tag_bb (const std::string &access_code, + int threshold, + const std::string &tag_name) +{ + return gnuradio::get_initial_sptr(new digital_correlate_access_code_tag_bb + (access_code, threshold, tag_name)); +} + + +digital_correlate_access_code_tag_bb::digital_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, "digital_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); +} + +digital_correlate_access_code_tag_bb::~digital_correlate_access_code_tag_bb () +{ +} + +bool +digital_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 +digital_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/gr-digital/lib/digital_descrambler_bb.cc b/gr-digital/lib/digital_descrambler_bb.cc new file mode 100644 index 000000000..68cba7145 --- /dev/null +++ b/gr-digital/lib/digital_descrambler_bb.cc @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * 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 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 <digital_descrambler_bb.h> +#include <gr_io_signature.h> + +digital_descrambler_bb_sptr +digital_make_descrambler_bb(int mask, int seed, int len) +{ + return gnuradio::get_initial_sptr(new digital_descrambler_bb(mask, seed, len)); +} + +digital_descrambler_bb::digital_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 +digital_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/gr-digital/lib/digital_diff_decoder_bb.cc b/gr-digital/lib/digital_diff_decoder_bb.cc new file mode 100644 index 000000000..7b8e8726a --- /dev/null +++ b/gr-digital/lib/digital_diff_decoder_bb.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <digital_diff_decoder_bb.h> +#include <gr_io_signature.h> + +digital_diff_decoder_bb_sptr +digital_make_diff_decoder_bb (unsigned int modulus) +{ + return gnuradio::get_initial_sptr(new digital_diff_decoder_bb(modulus)); +} + +digital_diff_decoder_bb::digital_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 +digital_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/gr-digital/lib/digital_diff_encoder_bb.cc b/gr-digital/lib/digital_diff_encoder_bb.cc new file mode 100644 index 000000000..bfbaba98f --- /dev/null +++ b/gr-digital/lib/digital_diff_encoder_bb.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <digital_diff_encoder_bb.h> +#include <gr_io_signature.h> + +digital_diff_encoder_bb_sptr +digital_make_diff_encoder_bb (unsigned int modulus) +{ + return gnuradio::get_initial_sptr(new digital_diff_encoder_bb(modulus)); +} + +digital_diff_encoder_bb::digital_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 +digital_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/gr-digital/lib/digital_diff_phasor_cc.cc b/gr-digital/lib/digital_diff_phasor_cc.cc new file mode 100644 index 000000000..8313a4de8 --- /dev/null +++ b/gr-digital/lib/digital_diff_phasor_cc.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <digital_diff_phasor_cc.h> +#include <gr_io_signature.h> + +digital_diff_phasor_cc_sptr +digital_make_diff_phasor_cc () +{ + return gnuradio::get_initial_sptr(new digital_diff_phasor_cc()); +} + +digital_diff_phasor_cc::digital_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); +} + + +digital_diff_phasor_cc::~digital_diff_phasor_cc(){} + +int +digital_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/gr-digital/lib/digital_framer_sink_1.cc b/gr-digital/lib/digital_framer_sink_1.cc new file mode 100644 index 000000000..ba1c5bd50 --- /dev/null +++ b/gr-digital/lib/digital_framer_sink_1.cc @@ -0,0 +1,192 @@ +/* -*- 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 <digital_framer_sink_1.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <stdexcept> +#include <string.h> + +#define VERBOSE 0 + +inline void +digital_framer_sink_1::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; +} + +inline void +digital_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 +digital_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; +} + +digital_framer_sink_1_sptr +digital_make_framer_sink_1(gr_msg_queue_sptr target_queue) +{ + return gnuradio::get_initial_sptr(new digital_framer_sink_1(target_queue)); +} + + +digital_framer_sink_1::digital_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(); +} + +digital_framer_sink_1::~digital_framer_sink_1 () +{ +} + +int +digital_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/gr-digital/lib/digital_glfsr_source_b.cc b/gr-digital/lib/digital_glfsr_source_b.cc new file mode 100644 index 000000000..e557e475a --- /dev/null +++ b/gr-digital/lib/digital_glfsr_source_b.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <digital_glfsr_source_b.h> +#include <gri_glfsr.h> +#include <gr_io_signature.h> +#include <stdexcept> + +digital_glfsr_source_b_sptr +digital_make_glfsr_source_b(int degree, bool repeat, int mask, int seed) +{ + return gnuradio::get_initial_sptr(new digital_glfsr_source_b + (degree, repeat, mask, seed)); +} + +digital_glfsr_source_b::digital_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("digital_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); +} + +digital_glfsr_source_b::~digital_glfsr_source_b() +{ + delete d_glfsr; +} + +int +digital_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 +digital_glfsr_source_b::mask() const +{ + return d_glfsr->mask(); +} diff --git a/gr-digital/lib/digital_glfsr_source_f.cc b/gr-digital/lib/digital_glfsr_source_f.cc new file mode 100644 index 000000000..5a7736ef8 --- /dev/null +++ b/gr-digital/lib/digital_glfsr_source_f.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <digital_glfsr_source_f.h> +#include <gri_glfsr.h> +#include <gr_io_signature.h> +#include <stdexcept> + +digital_glfsr_source_f_sptr +digital_make_glfsr_source_f(int degree, bool repeat, int mask, int seed) +{ + return gnuradio::get_initial_sptr(new digital_glfsr_source_f + (degree, repeat, mask, seed)); +} + +digital_glfsr_source_f::digital_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("digital_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); +} + +digital_glfsr_source_f::~digital_glfsr_source_f() +{ + delete d_glfsr; +} + +int +digital_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 +digital_glfsr_source_f::mask() const +{ + return d_glfsr->mask(); +} diff --git a/gr-digital/lib/digital_impl_glfsr.cc b/gr-digital/lib/digital_impl_glfsr.cc new file mode 100644 index 000000000..342980e53 --- /dev/null +++ b/gr-digital/lib/digital_impl_glfsr.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +#include <digital_impl_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 digital_impl_glfsr::glfsr_mask(int degree) +{ + if (degree < 1 || degree > 32) + throw std::runtime_error("digital_impl_glfsr::glfsr_mask(): degree must be between 1 and 32 inclusive"); + return s_polynomial_masks[degree]; +} diff --git a/gr-digital/lib/digital_map_bb.cc b/gr-digital/lib/digital_map_bb.cc new file mode 100644 index 000000000..1d8444a40 --- /dev/null +++ b/gr-digital/lib/digital_map_bb.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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 <digital_map_bb.h> +#include <gr_io_signature.h> + +digital_map_bb_sptr +digital_make_map_bb (const std::vector<int> &map) +{ + return gnuradio::get_initial_sptr(new digital_map_bb (map)); +} + +digital_map_bb::digital_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 +digital_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/gr-digital/lib/digital_packet_sink.cc b/gr-digital/lib/digital_packet_sink.cc new file mode 100644 index 000000000..92521376f --- /dev/null +++ b/gr-digital/lib/digital_packet_sink.cc @@ -0,0 +1,207 @@ +/* -*- 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 <digital_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 +digital_packet_sink::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; + d_shift_reg = 0; +} + +inline void +digital_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 +digital_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; +} + +digital_packet_sink_sptr +digital_make_packet_sink (const std::vector<unsigned char>& sync_vector, + gr_msg_queue_sptr target_queue, int threshold) +{ + return gnuradio::get_initial_sptr(new digital_packet_sink (sync_vector, target_queue, threshold)); +} + + +digital_packet_sink::digital_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(); +} + +digital_packet_sink::~digital_packet_sink () +{ +} + +int +digital_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/gr-digital/lib/digital_pfb_clock_sync_ccf.cc b/gr-digital/lib/digital_pfb_clock_sync_ccf.cc new file mode 100644 index 000000000..1a2d5970b --- /dev/null +++ b/gr-digital/lib/digital_pfb_clock_sync_ccf.cc @@ -0,0 +1,440 @@ +/* -*- 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 <cstdio> +#include <cmath> + +#include <digital_pfb_clock_sync_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +digital_pfb_clock_sync_ccf_sptr +digital_make_pfb_clock_sync_ccf(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) +{ + return gnuradio::get_initial_sptr(new digital_pfb_clock_sync_ccf + (sps, loop_bw, taps, + filter_size, + init_phase, + max_rate_deviation, + osps)); +} + +static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +digital_pfb_clock_sync_ccf::digital_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) + : gr_block ("pfb_clock_sync_ccf", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false), d_nfilters(filter_size), + d_max_dev(max_rate_deviation), + d_osps(osps), d_error(0), d_out_idx(0) +{ + d_nfilters = filter_size; + d_sps = floor(sps); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); + + // Store the last filter between calls to work + // The accumulator keeps track of overflow to increment the stride correctly. + // set it here to the fractional difference based on the initial phaes + d_k = init_phase; + d_rate = (sps-floor(sps))*(double)d_nfilters; + d_rate_i = (int)floor(d_rate); + d_rate_f = d_rate - (float)d_rate_i; + d_filtnum = (int)floor(d_k); + + d_filters = std::vector<gr_fir_ccf*>(d_nfilters); + d_diff_filters = std::vector<gr_fir_ccf*>(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilters); + for(int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +digital_pfb_clock_sync_ccf::~digital_pfb_clock_sync_ccf () +{ + for(int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +bool +digital_pfb_clock_sync_ccf::check_topology(int ninputs, int noutputs) +{ + return noutputs == 1 || noutputs == 4; +} + + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +digital_pfb_clock_sync_ccf::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +digital_pfb_clock_sync_ccf::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +digital_pfb_clock_sync_ccf::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +digital_pfb_clock_sync_ccf::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +digital_pfb_clock_sync_ccf::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +digital_pfb_clock_sync_ccf::get_damping_factor() const +{ + return d_damping; +} + +float +digital_pfb_clock_sync_ccf::get_alpha() const +{ + return d_alpha; +} + +float +digital_pfb_clock_sync_ccf::get_beta() const +{ + return d_beta; +} + +float +digital_pfb_clock_sync_ccf::get_clock_rate() const +{ + return d_rate_f; +} + +/******************************************************************* +*******************************************************************/ + +void +digital_pfb_clock_sync_ccf::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + + +void +digital_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter) +{ + int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // 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_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilters; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + // Make sure there is enough output space for d_osps outputs/input. + set_output_multiple(d_osps); + + d_updated = true; +} + +void +digital_pfb_clock_sync_ccf::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + std::vector<float> diff_filter(3); + diff_filter[0] = -1; + diff_filter[1] = 0; + diff_filter[2] = 1; + + float pwr = 0; + difftaps.push_back(0); + for(unsigned int i = 0; i < newtaps.size()-2; i++) { + float tap = 0; + for(int j = 0; j < 3; j++) { + tap += diff_filter[j]*newtaps[i+j]; + pwr += fabsf(tap); + } + difftaps.push_back(tap); + } + difftaps.push_back(0); + + for(unsigned int i = 0; i < difftaps.size(); i++) { + difftaps[i] *= pwr; + } +} + +std::string +digital_pfb_clock_sync_ccf::get_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_taps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_taps[i][j] << ", "; + } + str << d_taps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::string +digital_pfb_clock_sync_ccf::get_diff_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_dtaps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_dtaps[i][j] << ", "; + } + str << d_dtaps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_ccf::get_taps() +{ + return d_taps; +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_ccf::get_diff_taps() +{ + return d_dtaps; +} + +std::vector<float> +digital_pfb_clock_sync_ccf::get_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector<float> +digital_pfb_clock_sync_ccf::get_diff_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + + +int +digital_pfb_clock_sync_ccf::general_work(int noutput_items, + gr_vector_int &ninput_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]; + + float *err = NULL, *outrate = NULL, *outk = NULL; + if(output_items.size() == 4) { + err = (float *) output_items[1]; + outrate = (float*)output_items[2]; + outk = (float*)output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter - d_osps; + + int i = 0, count = 0; + float error_r, error_i; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + while(d_out_idx < d_osps) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + + out[i+d_out_idx] = d_filters[d_filtnum]->filter(&in[count+d_out_idx]); + d_k = d_k + d_rate_i + d_rate_f; // update phase + d_out_idx++; + + if(output_items.size() == 4) { + err[i] = d_error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } + + // We've run out of output items we can create; return now. + if(i+d_out_idx >= noutput_items) { + consume_each(count); + return i; + } + } + + // reset here; if we didn't complete a full osps samples last time, + // the early return would take care of it. + d_out_idx = 0; + + // Update the phase and rate estimates for this symbol + gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]); + error_r = out[i].real() * diff.real(); + error_i = out[i].imag() * diff.imag(); + d_error = (error_i + error_r) / 2.0; // average error from I&Q channel + + // Run the control loop to update the current phase (k) and + // tracking rate estimates based on the error value + d_rate_f = d_rate_f + d_beta*d_error; + d_k = d_k + d_alpha*d_error; + + // Keep our rate within a good range + d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); + + i+=d_osps; + count += (int)floor(d_sps); + } + + consume_each(count); + return i; +} diff --git a/gr-digital/lib/digital_pfb_clock_sync_fff.cc b/gr-digital/lib/digital_pfb_clock_sync_fff.cc new file mode 100644 index 000000000..0e7d2a52d --- /dev/null +++ b/gr-digital/lib/digital_pfb_clock_sync_fff.cc @@ -0,0 +1,434 @@ +/* -*- 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 <cstdio> +#include <cmath> + +#include <digital_pfb_clock_sync_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +digital_pfb_clock_sync_fff_sptr +digital_make_pfb_clock_sync_fff(double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) +{ + return gnuradio::get_initial_sptr(new digital_pfb_clock_sync_fff + (sps, gain, taps, + filter_size, + init_phase, + max_rate_deviation, + osps)); +} + +static int ios[] = {sizeof(float), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +digital_pfb_clock_sync_fff::digital_pfb_clock_sync_fff (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) + : gr_block ("pfb_clock_sync_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false), d_nfilters(filter_size), + d_max_dev(max_rate_deviation), + d_osps(osps), d_error(0), d_out_idx(0) +{ + d_nfilters = filter_size; + d_sps = floor(sps); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); + + // Store the last filter between calls to work + // The accumulator keeps track of overflow to increment the stride correctly. + // set it here to the fractional difference based on the initial phaes + d_k = init_phase; + d_rate = (sps-floor(sps))*(double)d_nfilters; + d_rate_i = (int)floor(d_rate); + d_rate_f = d_rate - (float)d_rate_i; + d_filtnum = (int)floor(d_k); + + d_filters = std::vector<gr_fir_fff*>(d_nfilters); + d_diff_filters = std::vector<gr_fir_fff*>(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilters); + for(int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +digital_pfb_clock_sync_fff::~digital_pfb_clock_sync_fff () +{ + for(int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +bool +digital_pfb_clock_sync_fff::check_topology(int ninputs, int noutputs) +{ + return noutputs == 1 || noutputs == 4; +} + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +digital_pfb_clock_sync_fff::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +digital_pfb_clock_sync_fff::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +digital_pfb_clock_sync_fff::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +digital_pfb_clock_sync_fff::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +digital_pfb_clock_sync_fff::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +digital_pfb_clock_sync_fff::get_damping_factor() const +{ + return d_damping; +} + +float +digital_pfb_clock_sync_fff::get_alpha() const +{ + return d_alpha; +} + +float +digital_pfb_clock_sync_fff::get_beta() const +{ + return d_beta; +} + +float +digital_pfb_clock_sync_fff::get_clock_rate() const +{ + return d_rate_f; +} + +/******************************************************************* +*******************************************************************/ + +void +digital_pfb_clock_sync_fff::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + + +void +digital_pfb_clock_sync_fff::set_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter) +{ + int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // 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_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilters; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + // Make sure there is enough output space for d_osps outputs/input. + set_output_multiple(d_osps); + + d_updated = true; +} + +void +digital_pfb_clock_sync_fff::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + std::vector<float> diff_filter(3); + diff_filter[0] = -1; + diff_filter[1] = 0; + diff_filter[2] = 1; + + float pwr = 0; + difftaps.push_back(0); + for(unsigned int i = 0; i < newtaps.size()-2; i++) { + float tap = 0; + for(int j = 0; j < 3; j++) { + tap += diff_filter[j]*newtaps[i+j]; + pwr += fabsf(tap); + } + difftaps.push_back(tap); + } + difftaps.push_back(0); + + for(unsigned int i = 0; i < difftaps.size(); i++) { + difftaps[i] *= pwr; + } +} + +std::string +digital_pfb_clock_sync_fff::get_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_taps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_taps[i][j] << ", "; + } + str << d_taps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::string +digital_pfb_clock_sync_fff::get_diff_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_dtaps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_dtaps[i][j] << ", "; + } + str << d_dtaps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_fff::get_taps() +{ + return d_taps; +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_fff::get_diff_taps() +{ + return d_dtaps; +} + +std::vector<float> +digital_pfb_clock_sync_fff::get_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector<float> +digital_pfb_clock_sync_fff::get_diff_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + +int +digital_pfb_clock_sync_fff::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + float *out = (float *) output_items[0]; + + float *err = NULL, *outrate = NULL, *outk = NULL; + if(output_items.size() == 4) { + err = (float *) output_items[1]; + outrate = (float*)output_items[2]; + outk = (float*)output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter - d_osps; + + int i = 0, count = 0; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + while(d_out_idx < d_osps) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + + out[i+d_out_idx] = d_filters[d_filtnum]->filter(&in[count+d_out_idx]); + d_k = d_k + d_rate_i + d_rate_f; // update phase + d_out_idx++; + + if(output_items.size() == 4) { + err[i] = d_error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } + + // We've run out of output items we can create; return now. + if(i+d_out_idx >= noutput_items) { + consume_each(count); + return i; + } + } + + // reset here; if we didn't complete a full osps samples last time, + // the early return would take care of it. + d_out_idx = 0; + + // Update the phase and rate estimates for this symbol + float diff = d_diff_filters[d_filtnum]->filter(&in[count]); + d_error = out[i] * diff; + + // Run the control loop to update the current phase (k) and + // tracking rate estimates based on the error value + d_rate_f = d_rate_f + d_beta*d_error; + d_k = d_k + d_alpha*d_error; + + // Keep our rate within a good range + d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); + + i+=d_osps; + count += (int)floor(d_sps); + } + + consume_each(count); + return i; +} diff --git a/gr-digital/lib/digital_pn_correlator_cc.cc b/gr-digital/lib/digital_pn_correlator_cc.cc new file mode 100644 index 000000000..43a3ddbd1 --- /dev/null +++ b/gr-digital/lib/digital_pn_correlator_cc.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_pn_correlator_cc.h> +#include <gr_io_signature.h> + +digital_pn_correlator_cc_sptr +digital_make_pn_correlator_cc(int degree, int mask, int seed) +{ + return gnuradio::get_initial_sptr(new digital_pn_correlator_cc + (degree, mask, seed)); +} + +digital_pn_correlator_cc::digital_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; +} + +digital_pn_correlator_cc::~digital_pn_correlator_cc() +{ + delete d_reference; +} + +int +digital_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/gr-digital/lib/digital_probe_density_b.cc b/gr-digital/lib/digital_probe_density_b.cc new file mode 100644 index 000000000..6b83d2ddb --- /dev/null +++ b/gr-digital/lib/digital_probe_density_b.cc @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 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 <digital_probe_density_b.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +digital_probe_density_b_sptr +digital_make_probe_density_b(double alpha) +{ + return gnuradio::get_initial_sptr(new digital_probe_density_b(alpha)); +} + +digital_probe_density_b::digital_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; +} + +digital_probe_density_b::~digital_probe_density_b() +{ +} + +int +digital_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 +digital_probe_density_b::set_alpha(double alpha) +{ + d_alpha = alpha; + d_beta = 1.0-d_alpha; +} + diff --git a/gr-digital/lib/digital_scrambler_bb.cc b/gr-digital/lib/digital_scrambler_bb.cc new file mode 100644 index 000000000..c81b09d8c --- /dev/null +++ b/gr-digital/lib/digital_scrambler_bb.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * 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 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 <digital_scrambler_bb.h> +#include <gr_io_signature.h> + +digital_scrambler_bb_sptr +digital_make_scrambler_bb(int mask, int seed, int len) +{ + return gnuradio::get_initial_sptr(new digital_scrambler_bb + (mask, seed, len)); +} + +digital_scrambler_bb::digital_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 +digital_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/gr-digital/lib/digital_simple_framer.cc b/gr-digital/lib/digital_simple_framer.cc new file mode 100644 index 000000000..5c194543c --- /dev/null +++ b/gr-digital/lib/digital_simple_framer.cc @@ -0,0 +1,102 @@ +/* -*- 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 <digital_simple_framer.h> +#include <digital_simple_framer_sync.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> +#include <string.h> + + +digital_simple_framer_sptr +digital_make_simple_framer (int payload_bytesize) +{ + return gnuradio::get_initial_sptr(new digital_simple_framer + (payload_bytesize)); +} + +digital_simple_framer::digital_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 +digital_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 +digital_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/gr-digital/python/generic_mod_demod.py b/gr-digital/python/generic_mod_demod.py index ae876e108..a6c4f3445 100644 --- a/gr-digital/python/generic_mod_demod.py +++ b/gr-digital/python/generic_mod_demod.py @@ -28,7 +28,7 @@ Generic modulation and demodulation. from gnuradio import gr from modulation_utils import extract_kwargs_from_options_for_class from utils import mod_codes -import digital_swig +import digital_swig as digital import math # default values (used in __init__ and add_options) @@ -121,12 +121,12 @@ class generic_mod(gr.hier_block2): gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST) if gray_coded == True: - self.symbol_mapper = gr.map_bb(self._constellation.pre_diff_code()) + self.symbol_mapper = digital.map_bb(self._constellation.pre_diff_code()) if differential: - self.diffenc = gr.diff_encoder_bb(arity) + self.diffenc = digital.diff_encoder_bb(arity) - self.chunks2symbols = gr.chunks_to_symbols_bc(self._constellation.points()) + self.chunks2symbols = digital.chunks_to_symbols_bc(self._constellation.points()) # pulse shaping filter nfilts = 32 @@ -269,28 +269,28 @@ class generic_demod(gr.hier_block2): # Frequency correction fll_ntaps = 55 - self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, - fll_ntaps, self._freq_bw) + self.freq_recov = digital.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, + fll_ntaps, self._freq_bw) # symbol timing recovery with RRC data filter taps = gr.firdes.root_raised_cosine(nfilts, nfilts*self._samples_per_symbol, 1.0, self._excess_bw, ntaps) - self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, - self._timing_bw, taps, - nfilts, nfilts//2, self._timing_max_dev) + self.time_recov = digital.pfb_clock_sync_ccf(self._samples_per_symbol, + self._timing_bw, taps, + nfilts, nfilts//2, self._timing_max_dev) fmin = -0.25 fmax = 0.25 - self.receiver = digital_swig.constellation_receiver_cb( + self.receiver = digital.constellation_receiver_cb( self._constellation, self._phase_bw, fmin, fmax) # Do differential decoding based on phase change of symbols if differential: - self.diffdec = gr.diff_decoder_bb(arity) + self.diffdec = digital.diff_decoder_bb(arity) if gray_coded: - self.symbol_mapper = gr.map_bb( + self.symbol_mapper = digital.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) # unpack the k bit vector into a stream of bits diff --git a/gr-digital/python/qa_bytes_to_syms.py b/gr-digital/python/qa_bytes_to_syms.py new file mode 100755 index 000000000..75475a95b --- /dev/null +++ b/gr-digital/python/qa_bytes_to_syms.py @@ -0,0 +1,51 @@ +#!/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 digital_swig as digital +import math + +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 = digital.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) + +if __name__ == '__main__': + gr_unittest.run(test_bytes_to_syms, "test_bytes_to_syms.xml") + diff --git a/gr-digital/python/qa_chunks_to_symbols.py b/gr-digital/python/qa_chunks_to_symbols.py new file mode 100755 index 000000000..63af10d8f --- /dev/null +++ b/gr-digital/python/qa_chunks_to_symbols.py @@ -0,0 +1,140 @@ +#!/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 digital_swig as digital + +class test_chunks_to_symbols(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_bc_001(self): + const = [ 1+0j, 0+1j, + -1+0j, 0-1j] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (1+0j, 0+1j, -1+0j, 0-1j, + 0-1j, -1+0j, 0+1j, 1+0j) + + src = gr.vector_source_b(src_data) + op = digital.chunks_to_symbols_bc(const) + + dst = gr.vector_sink_c() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_bf_002(self): + const = [-3, -1, 1, 3] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (-3, -1, 1, 3, + 3, 1, -1, -3) + + src = gr.vector_source_b(src_data) + op = digital.chunks_to_symbols_bf(const) + + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_ic_003(self): + const = [ 1+0j, 0+1j, + -1+0j, 0-1j] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (1+0j, 0+1j, -1+0j, 0-1j, + 0-1j, -1+0j, 0+1j, 1+0j) + + src = gr.vector_source_i(src_data) + op = digital.chunks_to_symbols_ic(const) + + dst = gr.vector_sink_c() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_if_004(self): + const = [-3, -1, 1, 3] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (-3, -1, 1, 3, + 3, 1, -1, -3) + + src = gr.vector_source_i(src_data) + op = digital.chunks_to_symbols_if(const) + + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_sc_005(self): + const = [ 1+0j, 0+1j, + -1+0j, 0-1j] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (1+0j, 0+1j, -1+0j, 0-1j, + 0-1j, -1+0j, 0+1j, 1+0j) + + src = gr.vector_source_s(src_data) + op = digital.chunks_to_symbols_sc(const) + + dst = gr.vector_sink_c() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + + def test_sf_006(self): + const = [-3, -1, 1, 3] + src_data = (0, 1, 2, 3, 3, 2, 1, 0) + expected_result = (-3, -1, 1, 3, + 3, 1, -1, -3) + + src = gr.vector_source_s(src_data) + op = digital.chunks_to_symbols_sf(const) + + dst = gr.vector_sink_f() + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + + actual_result = dst.data() + self.assertEqual(expected_result, actual_result) + +if __name__ == '__main__': + gr_unittest.run(test_chunks_to_symbols, "test_chunks_to_symbols.xml") diff --git a/gr-digital/python/qa_correlate_access_code.py b/gr-digital/python/qa_correlate_access_code.py index 6b6f25051..96246dcfb 100755 --- a/gr-digital/python/qa_correlate_access_code.py +++ b/gr-digital/python/qa_correlate_access_code.py @@ -21,7 +21,7 @@ # from gnuradio import gr, gr_unittest -import digital_swig +import digital_swig as digital import math default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -53,7 +53,7 @@ class test_correlate_access_code(gr_unittest.TestCase): src_data = (1, 0, 1, 1, 1, 1, 0, 1, 1) + pad + (0,) * 7 expected_result = pad + (1, 0, 1, 1, 3, 1, 0, 1, 1, 2) + (0,) * 6 src = gr.vector_source_b (src_data) - op = digital_swig.correlate_access_code_bb("1011", 0) + op = digital.correlate_access_code_bb("1011", 0) dst = gr.vector_sink_b () self.tb.connect (src, op, dst) self.tb.run () @@ -70,13 +70,28 @@ class test_correlate_access_code(gr_unittest.TestCase): src_data = code + (1, 0, 1, 1) + pad expected_result = pad + code + (3, 0, 1, 1) src = gr.vector_source_b (src_data) - op = digital_swig.correlate_access_code_bb(access_code, 0) + op = digital.correlate_access_code_bb(access_code, 0) dst = gr.vector_sink_b () self.tb.connect (src, op, dst) self.tb.run () result_data = dst.data () self.assertEqual (expected_result, result_data) + def test_003(self): + code = tuple(string_to_1_0_list(default_access_code)) + access_code = to_1_0_string(code) + pad = (0,) * 64 + #print code + #print access_code + src_data = code + (1, 0, 1, 1) + pad + expected_result = code + (1, 0, 1, 1) + pad + src = gr.vector_source_b (src_data) + op = digital.correlate_access_code_tag_bb(access_code, 0, "test") + dst = gr.vector_sink_b () + self.tb.connect (src, op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) if __name__ == '__main__': diff --git a/gr-digital/python/qa_diff_encoder.py b/gr-digital/python/qa_diff_encoder.py new file mode 100755 index 000000000..e4f5470af --- /dev/null +++ b/gr-digital/python/qa_diff_encoder.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# Copyright 2006,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 digital_swig as digital +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 = digital.diff_encoder_bb(modulus) + dec = digital.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 = digital.diff_encoder_bb(modulus) + dec = digital.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 = digital.diff_encoder_bb(modulus) + dec = digital.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/gr-digital/python/qa_diff_phasor_cc.py b/gr-digital/python/qa_diff_phasor_cc.py new file mode 100755 index 000000000..3e7617fe4 --- /dev/null +++ b/gr-digital/python/qa_diff_phasor_cc.py @@ -0,0 +1,49 @@ +#!/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 digital_swig as digital +import math + +class test_diff_phasor (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + 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 = digital.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) + +if __name__ == '__main__': + gr_unittest.run(test_diff_phasor, "test_diff_phasor.xml") + diff --git a/gr-digital/python/qa_framer_sink.py b/gr-digital/python/qa_framer_sink.py new file mode 100755 index 000000000..bccc86dc7 --- /dev/null +++ b/gr-digital/python/qa_framer_sink.py @@ -0,0 +1,98 @@ +#!/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 digital_swig as digital + +default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' + +def string_to_1_0_list(s): + r = [] + for ch in s: + x = ord(ch) + for i in range(8): + t = (x >> i) & 0x1 + r.append(t) + return r + +def to_1_0_string(L): + return ''.join(map(lambda x: chr(x + ord('0')), L)) + +class test_framker_sink(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001(self): + + code = (1, 1, 0, 1) + access_code = to_1_0_string(code) + header = tuple(2*[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]) # len=1 + pad = (0,) * 100 + src_data = code + header + (0,1,0,0,0,0,0,1) + pad + expected_data = 'A' + + rcvd_pktq = gr.msg_queue() + + src = gr.vector_source_b(src_data) + correlator = digital.correlate_access_code_bb(access_code, 0) + framer_sink = digital.framer_sink_1(rcvd_pktq) + vsnk = gr.vector_sink_b() + + self.tb.connect(src, correlator, framer_sink) + self.tb.connect(correlator, vsnk) + self.tb.run () + + result_data = rcvd_pktq.delete_head() + result_data = result_data.to_string() + self.assertEqual (expected_data, result_data) + + def test_002(self): + + code = tuple(string_to_1_0_list(default_access_code)) + access_code = to_1_0_string(code) + header = tuple(2*[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0]) # len=2 + pad = (0,) * 100 + src_data = code + header + (0,1,0,0,1,0,0,0) + (0,1,0,0,1,0,0,1) + pad + expected_data = 'HI' + + rcvd_pktq = gr.msg_queue() + + src = gr.vector_source_b(src_data) + correlator = digital.correlate_access_code_bb(access_code, 0) + framer_sink = digital.framer_sink_1(rcvd_pktq) + vsnk = gr.vector_sink_b() + + self.tb.connect(src, correlator, framer_sink) + self.tb.connect(correlator, vsnk) + self.tb.run () + + result_data = rcvd_pktq.delete_head() + result_data = result_data.to_string() + self.assertEqual (expected_data, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_framker_sink, "test_framker_sink.xml") + diff --git a/gr-digital/python/qa_glfsr_source.py b/gr-digital/python/qa_glfsr_source.py new file mode 100755 index 000000000..157520d7f --- /dev/null +++ b/gr-digital/python/qa_glfsr_source.py @@ -0,0 +1,95 @@ +#!/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 digital_swig as digital + +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 = digital.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 = digital.glfsr_source_b(degree, False) + b2f = digital.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 = digital.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 = digital.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/gr-digital/python/qa_map.py b/gr-digital/python/qa_map.py new file mode 100755 index 000000000..3ad99a2c1 --- /dev/null +++ b/gr-digital/python/qa_map.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 digital_swig as digital + +class test_map(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def helper(self, symbols): + src_data = [0, 1, 2, 3, 0, 1, 2, 3] + expected_data = map(lambda x: symbols[x], src_data) + src = gr.vector_source_b (src_data) + op = digital.map_bb(symbols) + dst = gr.vector_sink_b () + self.tb.connect (src, op, dst) + self.tb.run () + + result_data = list(dst.data()) + self.assertEqual (expected_data, result_data) + + def test_001(self): + symbols = [0, 0, 0, 0] + self.helper(symbols) + + def test_002(self): + symbols = [3, 2, 1, 0] + self.helper(symbols) + + def test_003(self): + symbols = [8-1, 32-1, 128, 256-1] + self.helper(symbols) + +if __name__ == '__main__': + gr_unittest.run(test_map, "test_map.xml") + diff --git a/gr-digital/python/qa_pfb_clock_sync.py b/gr-digital/python/qa_pfb_clock_sync.py new file mode 100755 index 000000000..06c8a60ba --- /dev/null +++ b/gr-digital/python/qa_pfb_clock_sync.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import digital_swig as digital +import random, cmath + +class test_pfb_clock_sync(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test01 (self): + # Test BPSK sync + excess_bw = 0.35 + + sps = 4 + loop_bw = cmath.pi/100.0 + nfilts = 32 + init_phase = nfilts/2 + max_rate_deviation = 1.5 + osps = 1 + + ntaps = 11 * int(sps*nfilts) + taps = gr.firdes.root_raised_cosine(nfilts, nfilts*sps, + 1.0, excess_bw, ntaps) + + self.test = digital.pfb_clock_sync_ccf(sps, loop_bw, taps, + nfilts, init_phase, + max_rate_deviation, + osps) + + data = 1000*[complex(1,0), complex(-1,0)] + self.src = gr.vector_source_c(data, False) + + # pulse shaping interpolation filter + rrc_taps = gr.firdes.root_raised_cosine( + nfilts, # gain + nfilts, # sampling rate based on 32 filters in resampler + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + self.rrc_filter = gr.pfb_arb_resampler_ccf(sps, rrc_taps) + + self.snk = gr.vector_sink_c() + + self.tb.connect(self.src, self.rrc_filter, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[complex(-1,0), complex(1,0)] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #for e,d in zip(expected_result, dst_data): + # print e, d + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + + def test02 (self): + # Test real BPSK sync + excess_bw = 0.35 + + sps = 4 + loop_bw = cmath.pi/100.0 + nfilts = 32 + init_phase = nfilts/2 + max_rate_deviation = 1.5 + osps = 1 + + ntaps = 11 * int(sps*nfilts) + taps = gr.firdes.root_raised_cosine(nfilts, nfilts*sps, + 1.0, excess_bw, ntaps) + + self.test = digital.pfb_clock_sync_fff(sps, loop_bw, taps, + nfilts, init_phase, + max_rate_deviation, + osps) + + data = 1000*[1, -1] + self.src = gr.vector_source_f(data, False) + + # pulse shaping interpolation filter + rrc_taps = gr.firdes.root_raised_cosine( + nfilts, # gain + nfilts, # sampling rate based on 32 filters in resampler + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + self.rrc_filter = gr.pfb_arb_resampler_fff(sps, rrc_taps) + + self.snk = gr.vector_sink_f() + + self.tb.connect(self.src, self.rrc_filter, self.test, self.snk) + self.tb.run() + + expected_result = 1000*[-1, 1] + dst_data = self.snk.data() + + # Only compare last Ncmp samples + Ncmp = 100 + len_e = len(expected_result) + len_d = len(dst_data) + expected_result = expected_result[len_e - Ncmp:] + dst_data = dst_data[len_d - Ncmp:] + + #for e,d in zip(expected_result, dst_data): + # print e, d + + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 1) + + +if __name__ == '__main__': + gr_unittest.run(test_pfb_clock_sync, "test_pfb_clock_sync.xml") diff --git a/volk/python/qa_square.py b/gr-digital/python/qa_pn_correlator_cc.py index c74bc25ef..377bef5fe 100755 --- a/volk/python/qa_square.py +++ b/gr-digital/python/qa_pn_correlator_cc.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2010 Free Software Foundation, Inc. +# Copyright 2007,2010,2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -21,27 +21,31 @@ # from gnuradio import gr, gr_unittest -import volk_swig as volk +import digital_swig as digital -class qa_volk(gr_unittest.TestCase): +class test_pn_correlator_cc(gr_unittest.TestCase): def setUp(self): - self.tb = gr.top_block() + self.tb = gr.top_block () def tearDown(self): self.tb = None - def test_001_square_ff(self): - src_data = (-3, 4, -5.5, 2, 3) - expected_result = (9, 16, 30.25, 4, 9) - src = gr.vector_source_f(src_data) - sqr = volk.square_ff() - dst = gr.vector_sink_f() - self.tb.connect(src, sqr) - self.tb.connect(sqr, dst) + def test_000_make(self): + c = digital.pn_correlator_cc(10) + + def test_001_correlate(self): + degree = 10 + length = 2**degree-1 + src = digital.glfsr_source_f(degree) + head = gr.head(gr.sizeof_float, length*length) + f2c = gr.float_to_complex() + corr = digital.pn_correlator_cc(degree) + dst = gr.vector_sink_c() + self.tb.connect(src, head, f2c, corr, dst) self.tb.run() - result_data = dst.data() - self.assertFloatTuplesAlmostEqual(expected_result, result_data, 6) + data = dst.data() + self.assertEqual(data[-1], (1.0+0j)) if __name__ == '__main__': - gr_unittest.main() + gr_unittest.run(test_pn_correlator_cc, "test_pn_correlator_cc.xml") diff --git a/gr-digital/python/qa_probe_density.py b/gr-digital/python/qa_probe_density.py new file mode 100755 index 000000000..c5b7e0e7c --- /dev/null +++ b/gr-digital/python/qa_probe_density.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 digital_swig as digital + +class test_probe_density(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001(self): + src_data = [0, 1, 0, 1] + expected_data = 1 + src = gr.vector_source_b (src_data) + op = digital.probe_density_b(1) + self.tb.connect (src, op) + self.tb.run () + + result_data = op.density() + self.assertEqual (expected_data, result_data) + + + def test_002(self): + src_data = [1, 1, 1, 1] + expected_data = 1 + src = gr.vector_source_b (src_data) + op = digital.probe_density_b(0.01) + self.tb.connect (src, op) + self.tb.run () + + result_data = op.density() + self.assertEqual (expected_data, result_data) + + def test_003(self): + src_data = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] + expected_data = 0.95243 + src = gr.vector_source_b (src_data) + op = digital.probe_density_b(0.01) + self.tb.connect (src, op) + self.tb.run () + + result_data = op.density() + print result_data + self.assertAlmostEqual (expected_data, result_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_probe_density, "test_probe_density.xml") + diff --git a/gr-digital/python/qa_scrambler.py b/gr-digital/python/qa_scrambler.py new file mode 100755 index 000000000..f5bd61242 --- /dev/null +++ b/gr-digital/python/qa_scrambler.py @@ -0,0 +1,65 @@ +#!/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 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 digital_swig as digital + +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 = digital.scrambler_bb(0x8a, 0x7F, 7) # CCSDS 7-bit scrambler + descrambler = digital.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 = digital.additive_scrambler_bb(0x8a, 0x7f, 7) + descrambler = digital.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 = digital.additive_scrambler_bb(0x8a, 0x7f, 7, 100) + descrambler = digital.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/gr-digital/python/qa_simple_framer.py b/gr-digital/python/qa_simple_framer.py new file mode 100755 index 000000000..09b2d329b --- /dev/null +++ b/gr-digital/python/qa_simple_framer.py @@ -0,0 +1,59 @@ +#!/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 digital_swig as digital +import math + +class test_simple_framer (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_simple_framer_001 (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 = digital.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_simple_framer, "test_simple_framer.xml") + diff --git a/gr-digital/swig/CMakeLists.txt b/gr-digital/swig/CMakeLists.txt index 6f2c2251a..0c129e181 100644 --- a/gr-digital/swig/CMakeLists.txt +++ b/gr-digital/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 # @@ -18,23 +18,107 @@ # Boston, MA 02110-1301, USA. ######################################################################## -# Setup swig generation +# 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_dict(name, sig, 'digital') + build_utils.expand_template(d, inp) + +") + +macro(expand_i root) + # make a list of the .i generated files + unset(expanded_files_i) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_i ${CMAKE_CURRENT_BINARY_DIR}/${name}.i) + endforeach(sig) + + #create a command to generate the .i files + add_custom_command( + OUTPUT ${expanded_files_i} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.i.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.i.t ${ARGN} + ) + + # Lists of generated i files + list(APPEND generated_swigs ${expanded_files_i}) +endmacro(expand_i) + + +######################################################################## +# Invoke macro to generate various sources +######################################################################## +expand_i(digital_chunks_to_symbols_XX bf bc sf sc if ic) + +add_custom_target(digital_generated_swigs DEPENDS + ${generated_swigs} +) + +######################################################################## +# Setup swig generation +######################################################################## include(GrSwig) -set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i) -set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include) +######################################################################## +# Create the master gengen swig include files +######################################################################## +set(generated_index ${CMAKE_CURRENT_BINARY_DIR}/digital_generated.i.in) +file(WRITE ${generated_index} " +// +// This file is machine generated. All edits will be overwritten +// +") + +file(APPEND ${generated_index} "%include \"gnuradio.i\"\n\n") +file(APPEND ${generated_index} "%{\n") + +foreach(swig_file ${generated_swigs}) + get_filename_component(name ${swig_file} NAME_WE) + file(APPEND ${generated_index} "#include<${name}.h>\n") +endforeach(swig_file) +file(APPEND ${generated_index} "%}\n") + +foreach(swig_file ${generated_swigs}) + get_filename_component(name ${swig_file} NAME) + file(APPEND ${generated_index} "%include<${name}>\n") +endforeach(swig_file) + +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${generated_index} ${CMAKE_CURRENT_BINARY_DIR}/digital_generated.i +) set(GR_SWIG_INCLUDE_DIRS ${GR_DIGITAL_INCLUDE_DIRS} ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/../include ) +# Setup swig docs to depend on includes and pull in from build directory set(GR_SWIG_LIBRARIES gnuradio-digital) - +set(GR_SWIG_TARGET_DEPS digital_generated_includes) +set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i) +set(GR_SWIG_DOC_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${CMAKE_CURRENT_BINARY_DIR}/../include) GR_SWIG_MAKE(digital_swig digital_swig.i) - GR_SWIG_INSTALL( TARGETS digital_swig DESTINATION ${GR_PYTHON_DIR}/gnuradio/digital @@ -45,19 +129,34 @@ install( FILES digital_swig.i ${CMAKE_CURRENT_BINARY_DIR}/digital_swig_doc.i + ${CMAKE_CURRENT_BINARY_DIR}/digital_generated.i + ${generated_swigs} + digital_additive_scrambler_bb.i digital_binary_slicer_fb.i + digital_bytes_to_syms.i digital_clock_recovery_mm_cc.i digital_clock_recovery_mm_ff.i + digital_cma_equalizer_cc.i digital_constellation.i digital_constellation_receiver_cb.i digital_constellation_decoder_cb.i digital_correlate_access_code_bb.i + digital_correlate_access_code_tag_bb.i digital_costas_loop_cc.i - digital_cma_equalizer_cc.i + digital_cpmmod_bc.i digital_crc32.i + digital_descrambler_bb.i + digital_diff_decoder_bb.i + digital_diff_encoder_bb.i + digital_diff_phasor_cc.i digital_fll_band_edge_cc.i + digital_framer_sink_1.i + digital_glfsr_source_b.i + digital_glfsr_source_f.i + digital_gmskmod_bc.i digital_lms_dd_equalizer_cc.i digital_kurtotic_equalizer_cc.i + digital_map_bb.i digital_mpsk_receiver_cc.i digital_mpsk_snr_est_cc.i digital_ofdm_cyclic_prefixer.i @@ -66,9 +165,14 @@ install( digital_ofdm_insert_preamble.i digital_ofdm_mapper_bcv.i digital_ofdm_sampler.i + digital_packet_sink.i + digital_pfb_clock_sync_ccf.i + digital_pfb_clock_sync_fff.i + digital_pn_correlator_cc.i + digital_probe_density_b.i digital_probe_mpsk_snr_est_c.i - digital_gmskmod_bc.i - digital_cpmmod_bc.i + digital_scrambler_bb.i + digital_simple_framer.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "digital_swig" ) diff --git a/volk/python/volk_square_ff.i b/gr-digital/swig/digital_additive_scrambler_bb.i index 5456c81fd..b063f0672 100644 --- a/volk/python/volk_square_ff.i +++ b/gr-digital/swig/digital_additive_scrambler_bb.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2010 Free Software Foundation, Inc. + * Copyright 2008,2010,2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -14,24 +14,18 @@ * 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. + * 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. */ -/* - * First arg is the package prefix. - * Second arg is the name of the class minus the prefix. - * - * This does some behind-the-scenes magic so we can - * access gr_example_square_ff from python as howto.square_ff - */ -GR_SWIG_BLOCK_MAGIC(volk,square_ff); +GR_SWIG_BLOCK_MAGIC(digital,additive_scrambler_bb); -volk_square_ff_sptr volk_make_square_ff (); +digital_additive_scrambler_bb_sptr +digital_make_additive_scrambler_bb(int mask, int seed, + int len, int count=0); -class volk_square_ff : public gr_sync_block +class digital_additive_scrambler_bb : public gr_sync_block { -private: - volk_square_ff(); }; diff --git a/gr-digital/swig/digital_bytes_to_syms.i b/gr-digital/swig/digital_bytes_to_syms.i new file mode 100644 index 000000000..cf23f035c --- /dev/null +++ b/gr-digital/swig/digital_bytes_to_syms.i @@ -0,0 +1,29 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,bytes_to_syms); + +digital_bytes_to_syms_sptr digital_make_bytes_to_syms(); + +class digital_bytes_to_syms : public gr_sync_interpolator +{ +}; diff --git a/gr-digital/swig/digital_chunks_to_symbols_XX.i.t b/gr-digital/swig/digital_chunks_to_symbols_XX.i.t new file mode 100644 index 000000000..a80ba2af1 --- /dev/null +++ b/gr-digital/swig/digital_chunks_to_symbols_XX.i.t @@ -0,0 +1,38 @@ +/* -*- 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@ + +GR_SWIG_BLOCK_MAGIC(digital,@BASE_NAME@); + +@SPTR_NAME@ digital_make_@BASE_NAME@ +(const std::vector<@O_TYPE@> &symbol_table, const int D = 1); + +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; } +}; diff --git a/gr-digital/swig/digital_constellation_decoder_cb.i b/gr-digital/swig/digital_constellation_decoder_cb.i index 53d3fe8e0..547f57ee6 100644 --- a/gr-digital/swig/digital_constellation_decoder_cb.i +++ b/gr-digital/swig/digital_constellation_decoder_cb.i @@ -31,7 +31,7 @@ class digital_constellation_decoder_cb : public gr_sync_block digital_constellation_decoder_cb (digital_constellation_sptr constellation); friend digital_constellation_decoder_cb_sptr - gr_make_constellation_decoder_cb (digital_constellation_sptr constellation); + digital_make_constellation_decoder_cb (digital_constellation_sptr constellation); public: ~digital_constellation_decoder_cb(); diff --git a/gr-digital/swig/digital_correlate_access_code_tag_bb.i b/gr-digital/swig/digital_correlate_access_code_tag_bb.i new file mode 100644 index 000000000..03f20148a --- /dev/null +++ b/gr-digital/swig/digital_correlate_access_code_tag_bb.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,correlate_access_code_tag_bb); + +digital_correlate_access_code_tag_bb_sptr +digital_make_correlate_access_code_tag_bb(const std::string &access_code, + int threshold, + const std::string &tag_name) + throw(std::out_of_range); + +class digital_correlate_access_code_tag_bb : public gr_sync_block +{ + public: + bool set_access_code(const std::string &access_code); +}; diff --git a/gr-digital/swig/digital_descrambler_bb.i b/gr-digital/swig/digital_descrambler_bb.i new file mode 100644 index 000000000..59de806fb --- /dev/null +++ b/gr-digital/swig/digital_descrambler_bb.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,descrambler_bb); + +digital_descrambler_bb_sptr +digital_make_descrambler_bb(int mask, int seed, int len); + +class digital_descrambler_bb : public gr_sync_block +{ +}; diff --git a/gr-digital/swig/digital_diff_decoder_bb.i b/gr-digital/swig/digital_diff_decoder_bb.i new file mode 100644 index 000000000..f9741c771 --- /dev/null +++ b/gr-digital/swig/digital_diff_decoder_bb.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,diff_decoder_bb) + +digital_diff_decoder_bb_sptr +digital_make_diff_decoder_bb(unsigned int modulus); + +class digital_diff_decoder_bb : public gr_sync_block +{ +}; diff --git a/gr-digital/swig/digital_diff_encoder_bb.i b/gr-digital/swig/digital_diff_encoder_bb.i new file mode 100644 index 000000000..45a4589bf --- /dev/null +++ b/gr-digital/swig/digital_diff_encoder_bb.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,diff_encoder_bb) + +digital_diff_encoder_bb_sptr +digital_make_diff_encoder_bb(unsigned int modulus); + +class digital_diff_encoder_bb : public gr_sync_block +{ +}; diff --git a/gr-digital/swig/digital_diff_phasor_cc.i b/gr-digital/swig/digital_diff_phasor_cc.i new file mode 100644 index 000000000..b1e20eb99 --- /dev/null +++ b/gr-digital/swig/digital_diff_phasor_cc.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,diff_phasor_cc) + +digital_diff_phasor_cc_sptr +digital_make_diff_phasor_cc(); + +class digital_diff_phasor_cc : public gr_sync_block +{ +}; diff --git a/gr-digital/swig/digital_framer_sink_1.i b/gr-digital/swig/digital_framer_sink_1.i new file mode 100644 index 000000000..a5c56560d --- /dev/null +++ b/gr-digital/swig/digital_framer_sink_1.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,framer_sink_1); + +digital_framer_sink_1_sptr +digital_make_framer_sink_1(gr_msg_queue_sptr target_queue); + +class digital_framer_sink_1 : public gr_sync_block +{ +}; diff --git a/gr-digital/swig/digital_glfsr_source_b.i b/gr-digital/swig/digital_glfsr_source_b.i new file mode 100644 index 000000000..b1c487209 --- /dev/null +++ b/gr-digital/swig/digital_glfsr_source_b.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,glfsr_source_b); + +digital_glfsr_source_b_sptr +digital_make_glfsr_source_b(int degree, bool repeat=true, + int mask=0, int seed=1) + throw (std::runtime_error); + +class digital_glfsr_source_b : public gr_sync_block +{ +public: + unsigned int period() const; + int mask() const; +}; diff --git a/gr-digital/swig/digital_glfsr_source_f.i b/gr-digital/swig/digital_glfsr_source_f.i new file mode 100644 index 000000000..4d94d8cd4 --- /dev/null +++ b/gr-digital/swig/digital_glfsr_source_f.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,glfsr_source_f); + +digital_glfsr_source_f_sptr +digital_make_glfsr_source_f(int degree, bool repeat=true, + int mask=0, int seed=1) + throw (std::runtime_error); + +class digital_glfsr_source_f : public gr_sync_block +{ +public: + unsigned int period() const; + int mask() const; +}; diff --git a/gr-digital/swig/digital_map_bb.i b/gr-digital/swig/digital_map_bb.i new file mode 100644 index 000000000..50117d4f5 --- /dev/null +++ b/gr-digital/swig/digital_map_bb.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,map_bb); + +digital_map_bb_sptr +digital_make_map_bb(const std::vector<int> &map); + +class digital_map_bb : public gr_sync_block +{ +}; + diff --git a/gr-digital/swig/digital_packet_sink.i b/gr-digital/swig/digital_packet_sink.i new file mode 100644 index 000000000..84f81f75c --- /dev/null +++ b/gr-digital/swig/digital_packet_sink.i @@ -0,0 +1,34 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,packet_sink) + +digital_packet_sink_sptr +digital_make_packet_sink(const std::vector<unsigned char>& sync_vector, + gr_msg_queue_sptr target_queue, + int threshold = -1); // -1 -> use default + +class digital_packet_sink : public gr_sync_block +{ + public: + bool carrier_sensed() const; +}; diff --git a/gr-digital/swig/digital_pfb_clock_sync_ccf.i b/gr-digital/swig/digital_pfb_clock_sync_ccf.i new file mode 100644 index 000000000..dbba614cc --- /dev/null +++ b/gr-digital/swig/digital_pfb_clock_sync_ccf.i @@ -0,0 +1,58 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,pfb_clock_sync_ccf); + +digital_pfb_clock_sync_ccf_sptr +digital_make_pfb_clock_sync_ccf(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5, + int osps=1); + +class digital_pfb_clock_sync_ccf : public gr_block +{ + public: + void set_taps(const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter); + + std::vector< std::vector<float> > get_taps(); + std::vector< std::vector<float> > get_diff_taps(); + std::vector<float> get_channel_taps(int channel); + std::vector<float> get_diff_channel_taps(int channel); + std::string get_taps_as_string(); + std::string get_diff_taps_as_string(); + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_max_rate_deviation(float m); + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_clock_rate() const; +}; diff --git a/gr-digital/swig/digital_pfb_clock_sync_fff.i b/gr-digital/swig/digital_pfb_clock_sync_fff.i new file mode 100644 index 000000000..956495e5d --- /dev/null +++ b/gr-digital/swig/digital_pfb_clock_sync_fff.i @@ -0,0 +1,58 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,pfb_clock_sync_fff); + +digital_pfb_clock_sync_fff_sptr +digital_make_pfb_clock_sync_fff(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5, + int osps=1); + +class digital_pfb_clock_sync_fff : public gr_block +{ + public: + void set_taps (const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + std::vector< std::vector<float> > get_taps(); + std::vector< std::vector<float> > get_diff_taps(); + std::vector<float> get_channel_taps(int channel); + std::vector<float> get_diff_channel_taps(int channel); + std::string get_taps_as_string(); + std::string get_diff_taps_as_string(); + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_max_rate_deviation(float m); + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_clock_rate() const; +}; diff --git a/gr-digital/swig/digital_pn_correlator_cc.i b/gr-digital/swig/digital_pn_correlator_cc.i new file mode 100644 index 000000000..11ccf12c2 --- /dev/null +++ b/gr-digital/swig/digital_pn_correlator_cc.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,pn_correlator_cc) + +digital_pn_correlator_cc_sptr +digital_make_pn_correlator_cc(int degree, int mask=0, int seed=1); + +class digital_pn_correlator_cc : public gr_sync_decimator +{ + protected: + digital_pn_correlator_cc(); +}; diff --git a/gr-digital/swig/digital_probe_density_b.i b/gr-digital/swig/digital_probe_density_b.i new file mode 100644 index 000000000..b0c8a119a --- /dev/null +++ b/gr-digital/swig/digital_probe_density_b.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,probe_density_b); + +digital_probe_density_b_sptr +digital_make_probe_density_b(double alpha); + +class digital_probe_density_b : public gr_sync_block +{ +public: + double density() const; + void set_alpha(double alpha); +}; diff --git a/gr-digital/swig/digital_scrambler_bb.i b/gr-digital/swig/digital_scrambler_bb.i new file mode 100644 index 000000000..ac9abef92 --- /dev/null +++ b/gr-digital/swig/digital_scrambler_bb.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,scrambler_bb); + +digital_scrambler_bb_sptr +digital_make_scrambler_bb(int mask, int seed, int len); + +class digital_scrambler_bb : public gr_sync_block +{ +}; diff --git a/gr-digital/swig/digital_simple_framer.i b/gr-digital/swig/digital_simple_framer.i new file mode 100644 index 000000000..a376317c5 --- /dev/null +++ b/gr-digital/swig/digital_simple_framer.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(digital,simple_framer); + +digital_simple_framer_sptr +digital_make_simple_framer(int payload_bytesize); + +class digital_simple_framer : public gr_block +{ +}; diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index 4e9c660bc..191076d75 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -35,8 +35,13 @@ enum snr_est_type_t { %include <gri_control_loop.i> +// Bring in generated blocks +%include "digital_generated.i" + %{ +#include "digital_additive_scrambler_bb.h" #include "digital_binary_slicer_fb.h" +#include "digital_bytes_to_syms.h" #include "digital_clock_recovery_mm_cc.h" #include "digital_clock_recovery_mm_ff.h" #include "digital_cma_equalizer_cc.h" @@ -44,11 +49,22 @@ enum snr_est_type_t { #include "digital_constellation_decoder_cb.h" #include "digital_constellation_receiver_cb.h" #include "digital_correlate_access_code_bb.h" +#include "digital_correlate_access_code_tag_bb.h" #include "digital_costas_loop_cc.h" +#include "digital_cpmmod_bc.h" #include "digital_crc32.h" +#include "digital_descrambler_bb.h" +#include "digital_diff_decoder_bb.h" +#include "digital_diff_encoder_bb.h" +#include "digital_diff_phasor_cc.h" #include "digital_fll_band_edge_cc.h" +#include "digital_framer_sink_1.h" +#include "digital_glfsr_source_b.h" +#include "digital_glfsr_source_f.h" +#include "digital_gmskmod_bc.h" #include "digital_kurtotic_equalizer_cc.h" #include "digital_lms_dd_equalizer_cc.h" +#include "digital_map_bb.h" #include "digital_mpsk_receiver_cc.h" #include "digital_mpsk_snr_est_cc.h" #include "digital_ofdm_cyclic_prefixer.h" @@ -57,11 +73,18 @@ enum snr_est_type_t { #include "digital_ofdm_insert_preamble.h" #include "digital_ofdm_mapper_bcv.h" #include "digital_ofdm_sampler.h" +#include "digital_packet_sink.h" +#include "digital_pfb_clock_sync_ccf.h" +#include "digital_pfb_clock_sync_fff.h" +#include "digital_pn_correlator_cc.h" +#include "digital_probe_density_b.h" #include "digital_probe_mpsk_snr_est_c.h" -#include "digital_cpmmod_bc.h" -#include "digital_gmskmod_bc.h" +#include "digital_scrambler_bb.h" +#include "digital_simple_framer.h" %} +%include "digital_additive_scrambler_bb.i" +%include "digital_bytes_to_syms.i" %include "digital_binary_slicer_fb.i" %include "digital_clock_recovery_mm_cc.i" %include "digital_clock_recovery_mm_ff.i" @@ -70,11 +93,22 @@ enum snr_est_type_t { %include "digital_constellation_decoder_cb.i" %include "digital_constellation_receiver_cb.i" %include "digital_correlate_access_code_bb.i" +%include "digital_correlate_access_code_tag_bb.i" %include "digital_costas_loop_cc.i" +%include "digital_cpmmod_bc.i" %include "digital_crc32.i" +%include "digital_descrambler_bb.i" +%include "digital_diff_decoder_bb.i" +%include "digital_diff_encoder_bb.i" +%include "digital_diff_phasor_cc.i" %include "digital_fll_band_edge_cc.i" +%include "digital_framer_sink_1.i" +%include "digital_glfsr_source_b.i" +%include "digital_glfsr_source_f.i" +%include "digital_gmskmod_bc.i" %include "digital_kurtotic_equalizer_cc.i" %include "digital_lms_dd_equalizer_cc.i" +%include "digital_map_bb.i" %include "digital_mpsk_receiver_cc.i" %include "digital_mpsk_snr_est_cc.i" %include "digital_ofdm_cyclic_prefixer.i" @@ -83,6 +117,11 @@ enum snr_est_type_t { %include "digital_ofdm_insert_preamble.i" %include "digital_ofdm_mapper_bcv.i" %include "digital_ofdm_sampler.i" +%include "digital_packet_sink.i" +%include "digital_pfb_clock_sync_ccf.i" +%include "digital_pfb_clock_sync_fff.i" +%include "digital_pn_correlator_cc.i" +%include "digital_probe_density_b.i" %include "digital_probe_mpsk_snr_est_c.i" -%include "digital_cpmmod_bc.i" -%include "digital_gmskmod_bc.i" +%include "digital_scrambler_bb.i" +%include "digital_simple_framer.i" diff --git a/gr-fft/CMakeLists.txt b/gr-fft/CMakeLists.txt new file mode 100644 index 000000000..7d76dc7f9 --- /dev/null +++ b/gr-fft/CMakeLists.txt @@ -0,0 +1,111 @@ +# 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) + +find_package(FFTW3f) + +######################################################################## +# Register component +######################################################################## +include(GrComponent) + +GR_REGISTER_COMPONENT("gr-fft" ENABLE_GR_FFT + ENABLE_GRUEL + ENABLE_VOLK + Boost_FOUND + ENABLE_GR_CORE + FFTW3F_FOUND +) + +GR_SET_GLOBAL(GR_FFT_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/lib + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +######################################################################## +# Begin conditional configuration +######################################################################## +if(ENABLE_GR_FFT) + +######################################################################## +# Setup CPack components +######################################################################## +include(GrPackage) +CPACK_SET(CPACK_COMPONENT_GROUP_FFT_DESCRIPTION "GNU Radio FFT Blocks") + +CPACK_COMPONENT("fft_runtime" + GROUP "FFT" + DISPLAY_NAME "Runtime" + DESCRIPTION "Runtime" + DEPENDS "core_runtime" +) + +CPACK_COMPONENT("fft_devel" + GROUP "FFT" + DISPLAY_NAME "Development" + DESCRIPTION "C++ headers, package config, import libraries" + DEPENDS "core_devel" +) + +CPACK_COMPONENT("fft_python" + GROUP "FFT" + DISPLAY_NAME "Python" + DESCRIPTION "Python modules for runtime; GRC xml files" + DEPENDS "core_python;fft_runtime" +) + +CPACK_COMPONENT("fft_swig" + GROUP "FFT" + DISPLAY_NAME "SWIG" + DESCRIPTION "SWIG development .i files" + DEPENDS "core_swig;fft_python;fft_devel" +) + +######################################################################## +# Add subdirectories +######################################################################## +add_subdirectory(include/fft) +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-fft.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-fft.pc +@ONLY) + +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/gnuradio-fft.pc + DESTINATION ${GR_LIBRARY_DIR}/pkgconfig + COMPONENT "fft_devel" +) + +endif(ENABLE_GR_FFT) diff --git a/gr-fft/doc/CMakeLists.txt b/gr-fft/doc/CMakeLists.txt new file mode 100644 index 000000000..96c42f030 --- /dev/null +++ b/gr-fft/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.fft + DESTINATION ${GR_PKG_DOC_DIR} +) diff --git a/gr-fft/doc/README.fft b/gr-fft/doc/README.fft new file mode 100644 index 000000000..3ea9e81f8 --- /dev/null +++ b/gr-fft/doc/README.fft @@ -0,0 +1,13 @@ +This is the gr-fft package. It contains signal processing blocks to +perform FFTs and FFT-related functionality. + +The Python namespace is in gnuradio.fft, which would be normally +imported as: + + from gnuradio import fft + +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(fft) diff --git a/gr-fft/doc/fft.dox b/gr-fft/doc/fft.dox new file mode 100644 index 000000000..5bf612d84 --- /dev/null +++ b/gr-fft/doc/fft.dox @@ -0,0 +1,29 @@ +/*! \page page_fft FFT Signal Processing Blocks + +\section Introduction + +This is the gr-fft package. It contains signal processing blocks to +perform FFTs and FFT-related functionality. + +The Python namespace is in gnuradio.fft, which would be normally +imported as: + +\code + from gnuradio import fft +\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(fft) +\endcode + +\section Dependencies + +The FFT blocks require the following dependencies. + +\li fftw3f (>= 3.0) http://www.fftw.org/download.html + +*/ diff --git a/gr-fft/gnuradio-fft.pc.in b/gr-fft/gnuradio-fft.pc.in new file mode 100644 index 000000000..eb4ddfd9f --- /dev/null +++ b/gr-fft/gnuradio-fft.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: gnuradio-fft +Description: GNU Radio's FFT signal processing blocks +Requires: gnuradio-core +Version: @LIBVER@ +Libs: -L${libdir} -lgnuradio-fft +Cflags: -I${includedir} diff --git a/gr-fft/grc/CMakeLists.txt b/gr-fft/grc/CMakeLists.txt new file mode 100644 index 000000000..632a9aaad --- /dev/null +++ b/gr-fft/grc/CMakeLists.txt @@ -0,0 +1,26 @@ +# 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 + fft_block_tree.xml + fft_vxx.xml + goertzel_fc.xml + DESTINATION ${GRC_BLOCKS_DIR} + COMPONENT "fft_python" +) diff --git a/gr-fft/grc/fft_block_tree.xml b/gr-fft/grc/fft_block_tree.xml new file mode 100644 index 000000000..3bda77eae --- /dev/null +++ b/gr-fft/grc/fft_block_tree.xml @@ -0,0 +1,36 @@ +<?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 FFT blocks. +################################################### + --> +<cat> + <name></name> <!-- Blank for Root Name --> + <cat> + <name>FFT</name> + <block>fft_vxx</block> + <block>goertzel_fc</block> + </cat> +</cat> diff --git a/gr-fft/grc/fft_vxx.xml b/gr-fft/grc/fft_vxx.xml new file mode 100644 index 000000000..69f12ace7 --- /dev/null +++ b/gr-fft/grc/fft_vxx.xml @@ -0,0 +1,88 @@ +<?xml version="1.0"?> +<!-- +################################################### +##FFT +################################################### + --> +<block> + <name>FFT</name> + <key>fft_vxx</key> + <import>from gnuradio import fft</import> + <import>from gnuradio import window</import> + <make>#if $type() == "complex" +fft.fft_vcc($fft_size, $forward, $window, $shift, $nthreads) +#else +fft.fft_vfc($fft_size, $forward, $window, $nthreads) +#end if</make> + <callback>set_nthreads($nthreads)</callback> + <param> + <name>Input Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex</name> + <key>complex</key> + <opt>hide_shift:</opt> + </option> + <option> + <name>Float</name> + <key>float</key> + <opt>hide_shift:all</opt> + </option> + </param> + <param> + <name>FFT Size</name> + <key>fft_size</key> + <value>1024</value> + <type>int</type> + </param> + <param> + <name>Forward/Reverse</name> + <key>forward</key> + <type>enum</type> + <option> + <name>Forward</name> + <key>True</key> + </option> + <option> + <name>Reverse</name> + <key>False</key> + </option> + </param> + <param> + <name>Window</name> + <key>window</key> + <value>window.blackmanharris(1024)</value> + <type>real_vector</type> + </param> + <param> + <name>Shift</name> + <key>shift</key> + <type>enum</type> + <hide>$type.hide_shift</hide> + <option> + <name>Yes</name> + <key>True</key> + </option> + <option> + <name>No</name> + <key>False</key> + </option> + </param> + <param> + <name>Num. Threads</name> + <key>nthreads</key> + <value>1</value> + <type>int</type> + </param> + <sink> + <name>in</name> + <type>$type</type> + <vlen>$fft_size</vlen> + </sink> + <source> + <name>out</name> + <type>complex</type> + <vlen>$fft_size</vlen> + </source> +</block> diff --git a/gr-fft/grc/goertzel_fc.xml b/gr-fft/grc/goertzel_fc.xml new file mode 100644 index 000000000..371284358 --- /dev/null +++ b/gr-fft/grc/goertzel_fc.xml @@ -0,0 +1,37 @@ +<?xml version="1.0"?> +<!-- +################################################### +##Goertzel +################################################### + --> +<block> + <name>Goertzel</name> + <key>goertzel_fc</key> + <import>from gnuradio import fft</import> + <make>fft.goertzel_fc($rate, $len, $freq)</make> + <callback>set_freq($freq)</callback> + <callback>set_rate($rate)</callback> + <param> + <name>Rate</name> + <key>rate</key> + <type>int</type> + </param> + <param> + <name>Length</name> + <key>len</key> + <type>int</type> + </param> + <param> + <name>Frequency</name> + <key>freq</key> + <type>real</type> + </param> + <sink> + <name>in</name> + <type>float</type> + </sink> + <source> + <name>out</name> + <type>complex</type> + </source> +</block> diff --git a/gr-fft/include/fft/CMakeLists.txt b/gr-fft/include/fft/CMakeLists.txt new file mode 100644 index 000000000..bce3da674 --- /dev/null +++ b/gr-fft/include/fft/CMakeLists.txt @@ -0,0 +1,33 @@ +# 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 header files +######################################################################## +install(FILES + api.h + fft.h + fft_vcc.h + fft_vfc.h + goertzel.h + goertzel_fc.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/fft + COMPONENT "fft_devel" +) + diff --git a/gr-fft/include/fft/api.h b/gr-fft/include/fft/api.h new file mode 100644 index 000000000..eef456373 --- /dev/null +++ b/gr-fft/include/fft/api.h @@ -0,0 +1,33 @@ +/* + * 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_FFT_API_H +#define INCLUDED_FFT_API_H + +#include <gruel/attributes.h> + +#ifdef gnuradio_fft_EXPORTS +# define FFT_API __GR_ATTR_EXPORT +#else +# define FFT_API __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_FFT_API_H */ diff --git a/gr-fft/include/fft/fft.h b/gr-fft/include/fft/fft.h new file mode 100644 index 000000000..5cc2e21e8 --- /dev/null +++ b/gr-fft/include/fft/fft.h @@ -0,0 +1,195 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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 _FFT_FFT_H_ +#define _FFT_FFT_H_ + +/* + * Wrappers for FFTW single precision 1d dft + */ + +#include <fft/api.h> +#include <gr_complex.h> +#include <boost/thread.hpp> + +namespace gr { + namespace fft { + + + /*! \brief Helper function for allocating complex fft buffers + */ + gr_complex* malloc_complex(int size); + + /*! \brief Helper function for allocating float fft buffers + */ + float* malloc_float(int size); + + /*! \brief Helper function for freeing fft buffers + */ + void free(void *b); + + /*! + * \brief Export reference to planner mutex for those apps that + * want to use FFTW w/o using the fft_impl_fftw* classes. + */ + class FFT_API planner { + public: + typedef boost::mutex::scoped_lock scoped_lock; + /*! + * Return reference to planner mutex + */ + static boost::mutex &mutex(); + }; + + /*! + * \brief FFT: complex in, complex out + * \ingroup misc + */ + class FFT_API fft_complex { + int d_fft_size; + int d_nthreads; + gr_complex *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + + public: + fft_complex(int fft_size, bool forward = true, int nthreads=1); + virtual ~fft_complex(); + + /* + * These return pointers to buffers owned by fft_impl_fft_complex + * into which input and output take place. It's done this way in + * order to ensure optimal alignment for SIMD instructions. + */ + gr_complex *get_inbuf() const { return d_inbuf; } + gr_complex *get_outbuf() const { return d_outbuf; } + + int inbuf_length() const { return d_fft_size; } + int outbuf_length() const { return d_fft_size; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in + * outbuf. + */ + void execute(); + }; + + /*! + * \brief FFT: real in, complex out + * \ingroup misc + */ + class FFT_API fft_real_fwd { + int d_fft_size; + int d_nthreads; + float *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + + public: + fft_real_fwd (int fft_size, int nthreads=1); + virtual ~fft_real_fwd (); + + /* + * These return pointers to buffers owned by fft_impl_fft_real_fwd + * into which input and output take place. It's done this way in + * order to ensure optimal alignment for SIMD instructions. + */ + float *get_inbuf() const { return d_inbuf; } + gr_complex *get_outbuf() const { return d_outbuf; } + + int inbuf_length() const { return d_fft_size; } + int outbuf_length() const { return d_fft_size / 2 + 1; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in + * outbuf. + */ + void execute(); + }; + + /*! + * \brief FFT: complex in, float out + * \ingroup misc + */ + class FFT_API fft_real_rev { + int d_fft_size; + int d_nthreads; + gr_complex *d_inbuf; + float *d_outbuf; + void *d_plan; + + public: + fft_real_rev(int fft_size, int nthreads=1); + virtual ~fft_real_rev(); + + /* + * These return pointers to buffers owned by fft_impl_fft_real_rev + * into which input and output take place. It's done this way in + * order to ensure optimal alignment for SIMD instructions. + */ + gr_complex *get_inbuf() const { return d_inbuf; } + float *get_outbuf() const { return d_outbuf; } + + int inbuf_length() const { return d_fft_size / 2 + 1; } + int outbuf_length() const { return d_fft_size; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in + * outbuf. + */ + void execute(); + }; + + } /* namespace fft */ +} /*namespace gr */ + +#endif /* _FFT_FFT_H_ */ diff --git a/gr-fft/include/fft/fft_vcc.h b/gr-fft/include/fft/fft_vcc.h new file mode 100644 index 000000000..cb07b166d --- /dev/null +++ b/gr-fft/include/fft/fft_vcc.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifndef INCLUDED_FFT_FFT_VCC_H +#define INCLUDED_FFT_FFT_VCC_H + +#include <fft/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vcc : virtual public gr_sync_block + { + public: + + // gr::fft::fft_vcc::sptr + typedef boost::shared_ptr<fft_vcc> sptr; + + /*! + * \brief Compute forward or reverse FFT. complex vector in / complex vector out. + * \ingroup dft_blk + */ + static sptr make(int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); + + virtual void set_nthreads(int n) = 0; + + virtual int nthreads() const = 0; + + virtual bool set_window(const std::vector<float> &window) = 0; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VCC_H */ diff --git a/gr-fft/include/fft/fft_vfc.h b/gr-fft/include/fft/fft_vfc.h new file mode 100644 index 000000000..ec441d66a --- /dev/null +++ b/gr-fft/include/fft/fft_vfc.h @@ -0,0 +1,57 @@ +/* -*- 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_FFT_FFT_VFC_H +#define INCLUDED_FFT_FFT_VFC_H + +#include <fft/api.h> +#include <gr_sync_block.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vfc : virtual public gr_sync_block + { + public: + + // gr::fft::fft_vfc::sptr + typedef boost::shared_ptr<fft_vfc> sptr; + + /*! + * \brief Compute forward or reverse FFT. float vector in / complex vector out. + * \ingroup dft_blk + */ + static sptr make(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + + virtual void set_nthreads(int n) = 0; + + virtual int nthreads() const = 0; + + virtual bool set_window(const std::vector<float> &window) = 0; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VFC_H */ diff --git a/gr-fft/include/fft/goertzel.h b/gr-fft/include/fft/goertzel.h new file mode 100644 index 000000000..ff37355e6 --- /dev/null +++ b/gr-fft/include/fft/goertzel.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_FFT_IMPL_GOERTZEL_H +#define INCLUDED_FFT_IMPL_GOERTZEL_H + +#include <fft/api.h> +#include <gr_types.h> + +namespace gr { + namespace fft { + + /*! + * \brief Implements Goertzel single-bin DFT calculation + * \ingroup misc + */ + class FFT_API goertzel + { + public: + goertzel(){} + goertzel(int rate, int len, float freq); + + void set_params(int rate, int len, float freq); + + // Process a input array + gr_complex batch(float *in); + + // Process sample by sample + void input(const float &in); + gr_complex output(); + bool ready() const { return d_processed == d_len; } + + private: + float d_d1; + float d_d2; + float d_wr; + float d_wi; + int d_len; + int d_processed; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_IMPL_GOERTZEL_H */ diff --git a/gr-fft/include/fft/goertzel_fc.h b/gr-fft/include/fft/goertzel_fc.h new file mode 100644 index 000000000..5b3c8f1c4 --- /dev/null +++ b/gr-fft/include/fft/goertzel_fc.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_FFT_GOERTZEL_FC_H +#define INCLUDED_FFT_GOERTZEL_FC_H + +#include <fft/api.h> +#include <gr_sync_decimator.h> + +namespace gr { + namespace fft { + + class FFT_API goertzel_fc : virtual public gr_sync_decimator + { + public: + + // gr::fft::goertzel_fc::sptr + typedef boost::shared_ptr<goertzel_fc> sptr; + + /*! + * \brief Goertzel single-bin DFT calculation. + * \ingroup dft_blk + */ + static sptr make(int rate, int len, float freq); + + virtual void set_freq (float freq) = 0; + + virtual void set_rate (int rate) = 0; + + virtual float freq() = 0; + + virtual int rate() = 0; + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_GOERTZEL_FC_H */ diff --git a/gr-fft/lib/CMakeLists.txt b/gr-fft/lib/CMakeLists.txt new file mode 100644 index 000000000..e2f17a183 --- /dev/null +++ b/gr-fft/lib/CMakeLists.txt @@ -0,0 +1,59 @@ +# 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 the include and linker paths +######################################################################## +include_directories( + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_FFT_INCLUDE_DIRS} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} +) + +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}) + +######################################################################## +# Setup library +######################################################################## +list(APPEND fft_sources + fft.cc + fft_vcc_fftw.cc + fft_vfc_fftw.cc + goertzel_fc_impl.cc + goertzel.cc +) + +list(APPEND fft_libs + gnuradio-core + ${Boost_LIBRARIES} + ${FFT_LIBRARIES} + ${FFTW3F_LIBRARIES} +) + +add_library(gnuradio-fft SHARED ${fft_sources}) +target_link_libraries(gnuradio-fft ${fft_libs}) +GR_LIBRARY_FOO(gnuradio-fft RUNTIME_COMPONENT "fft_runtime" DEVEL_COMPONENT "fft_devel") diff --git a/gr-fft/lib/fft.cc b/gr-fft/lib/fft.cc new file mode 100644 index 000000000..6074236e1 --- /dev/null +++ b/gr-fft/lib/fft.cc @@ -0,0 +1,338 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2008,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. + */ + +#include <fft/fft.h> +#include <gr_sys_paths.h> +#include <fftw3.h> + +#ifdef _MSC_VER //http://www.fftw.org/install/windows.html#DLLwisdom +static void my_fftw_write_char(char c, void *f) { fputc(c, (FILE *) f); } +#define fftw_export_wisdom_to_file(f) fftw_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwf_export_wisdom_to_file(f) fftwf_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwl_export_wisdom_to_file(f) fftwl_export_wisdom(my_fftw_write_char, (void*) (f)) + +static int my_fftw_read_char(void *f) { return fgetc((FILE *) f); } +#define fftw_import_wisdom_from_file(f) fftw_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwf_import_wisdom_from_file(f) fftwf_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwl_import_wisdom_from_file(f) fftwl_import_wisdom(my_fftw_read_char, (void*) (f)) +#endif //_MSC_VER + +#include <gr_complex.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <cassert> +#include <stdexcept> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +namespace fs = boost::filesystem; + +namespace gr { + namespace fft { + + gr_complex * + malloc_complex(int size) + { + return (gr_complex*)fftwf_malloc(sizeof(gr_complex)*size); + } + + float * + malloc_float(int size) + { + return (float*)fftwf_malloc(sizeof(float)*size); + } + + void + free(void *b) + { + fftwf_free(b); + } + + boost::mutex & + planner::mutex() + { + static boost::mutex s_planning_mutex; + + return s_planning_mutex; + } + + static const char * + wisdom_filename() + { + static fs::path path; + path = fs::path(gr_appdata_path()) / ".gr_fftw_wisdom"; + return path.string().c_str(); + } + + static void + import_wisdom() + { + const char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "r"); + if (fp != 0){ + int r = fftwf_import_wisdom_from_file (fp); + fclose (fp); + if (!r){ + fprintf (stderr, "gr::fft: can't import wisdom from %s\n", filename); + } + } + } + + static void + config_threading(int nthreads) + { + static int fftw_threads_inited = 0; + +#ifdef FFTW3F_THREADS + if (fftw_threads_inited == 0) + { + fftw_threads_inited = 1; + fftwf_init_threads(); + } + + fftwf_plan_with_nthreads(nthreads); +#endif + } + + static void + export_wisdom() + { + const char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "w"); + if (fp != 0){ + fftwf_export_wisdom_to_file (fp); + fclose (fp); + } + else { + fprintf (stderr, "fft_impl_fftw: "); + perror (filename); + } + } + +// ---------------------------------------------------------------- + + fft_complex::fft_complex(int fft_size, bool forward, int nthreads) + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("fft_impl_fftw: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + config_threading(nthreads); + import_wisdom(); // load prior wisdom from disk + + d_plan = fftwf_plan_dft_1d (fft_size, + reinterpret_cast<fftwf_complex *>(d_inbuf), + reinterpret_cast<fftwf_complex *>(d_outbuf), + forward ? FFTW_FORWARD : FFTW_BACKWARD, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gr::fft: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_1d failed"); + } + export_wisdom(); // store new wisdom to disk + } + + fft_complex::~fft_complex() + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); + } + + void + fft_complex::set_nthreads(int n) + { + if (n <= 0) + throw std::out_of_range ("gr::fft: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif + } + + void + fft_complex::execute() + { + fftwf_execute((fftwf_plan) d_plan); + } + +// ---------------------------------------------------------------- + + fft_real_fwd::fft_real_fwd (int fft_size, int nthreads) + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gr::fft: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (float *) fftwf_malloc (sizeof (float) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + config_threading(nthreads); + import_wisdom(); // load prior wisdom from disk + + d_plan = fftwf_plan_dft_r2c_1d (fft_size, + d_inbuf, + reinterpret_cast<fftwf_complex *>(d_outbuf), + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gr::fft::fft_real_fwd: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed"); + } + export_wisdom(); // store new wisdom to disk + } + + fft_real_fwd::~fft_real_fwd() + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); + } + + void + fft_real_fwd::set_nthreads(int n) + { + if (n <= 0) + throw std::out_of_range ("gr::fft::fft_real_fwd::set_nthreads: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif + } + + void + fft_real_fwd::execute() + { + fftwf_execute ((fftwf_plan) d_plan); + } + + // ---------------------------------------------------------------- + + fft_real_rev::fft_real_rev(int fft_size, int nthreads) + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gr::fft::fft_real_rev: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (float *) fftwf_malloc (sizeof (float) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + config_threading(nthreads); + import_wisdom(); // load prior wisdom from disk + + // FIXME If there's ever a chance that the planning functions + // will be called in multiple threads, we've got to ensure single + // threaded access. They are not thread-safe. + d_plan = fftwf_plan_dft_c2r_1d (fft_size, + reinterpret_cast<fftwf_complex *>(d_inbuf), + d_outbuf, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gr::fft::fft_real_rev: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed"); + } + export_wisdom (); // store new wisdom to disk + } + + fft_real_rev::~fft_real_rev () + { + // Hold global mutex during plan construction and destruction. + planner::scoped_lock lock(planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); + } + + void + fft_real_rev::set_nthreads(int n) + { + if (n <= 0) + throw std::out_of_range ("gr::fft::fft_real_rev::set_nthreads: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif + } + + void + fft_real_rev::execute () + { + fftwf_execute ((fftwf_plan) d_plan); + } + + } /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/fft_vcc_fftw.cc b/gr-fft/lib/fft_vcc_fftw.cc new file mode 100644 index 000000000..ebcd5ec53 --- /dev/null +++ b/gr-fft/lib/fft_vcc_fftw.cc @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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 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_vcc_fftw.h" +#include <gr_io_signature.h> +#include <math.h> +#include <string.h> + +namespace gr { + namespace fft { + + fft_vcc::sptr fft_vcc::make(int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) + { + return gnuradio::get_initial_sptr(new fft_vcc_fftw + (fft_size, forward, window, + shift, nthreads)); + } + + fft_vcc_fftw::fft_vcc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) + : gr_sync_block("fft_vcc_fftw", + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex)), + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex))), + d_fft_size(fft_size), d_forward(forward), d_shift(shift) + { + d_fft = new fft_complex(d_fft_size, forward, nthreads); + } + + fft_vcc_fftw::~fft_vcc_fftw() + { + delete d_fft; + } + + void + fft_vcc_fftw::set_nthreads(int n) + { + d_fft->set_nthreads(n); + } + + int + fft_vcc_fftw::nthreads() const + { + return d_fft->nthreads(); + } + + bool + fft_vcc_fftw::set_window(const std::vector<float> &window) + { + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; + } + + int + fft_vcc_fftw::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 input_data_size = input_signature()->sizeof_stream_item (0); + unsigned int output_data_size = output_signature()->sizeof_stream_item (0); + + int count = 0; + + while(count++ < noutput_items) { + + // copy input into optimally aligned buffer + if(d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + if(!d_forward && d_shift) { + unsigned int offset = (!d_forward && d_shift)?(d_fft_size/2):0; + int fft_m_offset = d_fft_size - offset; + for(unsigned int i = 0; i < offset; i++) // apply window + dst[i+fft_m_offset] = in[i] * d_window[i]; + for(unsigned int i = offset; i < d_fft_size; i++) // apply window + dst[i-offset] = in[i] * d_window[i]; + } + else { + for(unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + } + else { + if(!d_forward && d_shift) { // apply an ifft shift on the data + gr_complex *dst = d_fft->get_inbuf(); + unsigned int len = (unsigned int)(floor(d_fft_size/2.0)); // half length of complex array + memcpy(&dst[0], &in[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex)*len); + } + else { + memcpy(d_fft->get_inbuf(), in, input_data_size); + } + } + + // compute the fft + d_fft->execute(); + + // copy result to our output + if(d_forward && d_shift) { // apply a fft shift on the data + unsigned int len = (unsigned int)(ceil(d_fft_size/2.0)); + memcpy(&out[0], &d_fft->get_outbuf()[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&out[d_fft_size - len], &d_fft->get_outbuf()[0], sizeof(gr_complex)*len); + } + else { + memcpy (out, d_fft->get_outbuf (), output_data_size); + } + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; + } + + } /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/fft_vcc_fftw.h b/gr-fft/lib/fft_vcc_fftw.h new file mode 100644 index 000000000..ea15dd07b --- /dev/null +++ b/gr-fft/lib/fft_vcc_fftw.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifndef INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H +#define INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H + +#include <fft/fft_vcc.h> +#include <fft/fft.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vcc_fftw : public fft_vcc + { + private: + fft_complex *d_fft; + unsigned int d_fft_size; + std::vector<float> d_window; + bool d_forward; + bool d_shift; + + public: + fft_vcc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads=1); + + ~fft_vcc_fftw(); + + void set_nthreads(int n); + int nthreads() const; + bool set_window(const std::vector<float> &window); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VCC_FFTW_IMPL_H */ diff --git a/gr-fft/lib/fft_vfc_fftw.cc b/gr-fft/lib/fft_vfc_fftw.cc new file mode 100644 index 000000000..8f9b127e5 --- /dev/null +++ b/gr-fft/lib/fft_vfc_fftw.cc @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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 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_vfc_fftw.h" +#include <gr_io_signature.h> +#include <math.h> +#include <string.h> + +namespace gr { + namespace fft { + + fft_vfc::sptr fft_vfc::make(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads) + { + return gnuradio::get_initial_sptr(new fft_vfc_fftw + (fft_size, forward, window, + nthreads)); + } + + fft_vfc_fftw::fft_vfc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads) + : gr_sync_block("fft_vfc_fftw", + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex)), + gr_make_io_signature(1, 1, fft_size * sizeof(gr_complex))), + d_fft_size(fft_size), d_forward(forward) + { + d_fft = new fft_complex(d_fft_size, forward, nthreads); + } + + fft_vfc_fftw::~fft_vfc_fftw() + { + delete d_fft; + } + + void + fft_vfc_fftw::set_nthreads(int n) + { + d_fft->set_nthreads(n); + } + + int + fft_vfc_fftw::nthreads() const + { + return d_fft->nthreads(); + } + + bool + fft_vfc_fftw::set_window(const std::vector<float> &window) + { + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; + } + + int + fft_vfc_fftw::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]; + gr_complex *out = (gr_complex *)output_items[0]; + + unsigned int output_data_size = output_signature()->sizeof_stream_item (0); + + int count = 0; + + while(count++ < noutput_items) { + + // copy input into optimally aligned buffer + if(d_window.size()) { + gr_complex *dst = d_fft->get_inbuf(); + for(unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + else { + gr_complex *dst = d_fft->get_inbuf(); + for(unsigned int i = 0; i < d_fft_size; i++) // float to complex conversion + dst[i] = in[i]; + } + + // compute the fft + d_fft->execute(); + + // copy result to output stream + memcpy(out, d_fft->get_outbuf(), output_data_size); + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; + } + + } /* namespace fft */ +} /* namespace gr */ + diff --git a/gr-fft/lib/fft_vfc_fftw.h b/gr-fft/lib/fft_vfc_fftw.h new file mode 100644 index 000000000..1b6f78ba6 --- /dev/null +++ b/gr-fft/lib/fft_vfc_fftw.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifndef INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H +#define INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H + +#include <fft/fft_vfc.h> +#include <fft/fft.h> + +namespace gr { + namespace fft { + + class FFT_API fft_vfc_fftw : public fft_vfc + { + private: + fft_complex *d_fft; + unsigned int d_fft_size; + std::vector<float> d_window; + bool d_forward; + + public: + fft_vfc_fftw(int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + + ~fft_vfc_fftw(); + + void set_nthreads(int n); + int nthreads() const; + bool set_window(const std::vector<float> &window); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_FFT_VFC_FFTW_IMPL_H */ diff --git a/gr-fft/lib/goertzel.cc b/gr-fft/lib/goertzel.cc new file mode 100644 index 000000000..4bcd5ee19 --- /dev/null +++ b/gr-fft/lib/goertzel.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <cmath> +#include <fft/goertzel.h> + +namespace gr { + namespace fft { + + goertzel::goertzel(int rate, int len, float freq) + { + set_params(rate, len, freq); + } + + void + goertzel::set_params(int rate, int len, float freq) + { + d_d1 = 0.0; + d_d2 = 0.0; + + float w = 2.0*M_PI*freq/rate; + d_wr = 2.0*std::cos(w); + d_wi = std::sin(w); + d_len = len; + d_processed = 0; + } + + gr_complex + goertzel::batch(float *in) + { + d_d1 = 0.0; + d_d2 = 0.0; + + for(int i = 0; i < d_len; i++) + input(in[i]); + + return output(); + } + + void + goertzel::input(const float &input) + { + float y = input + d_wr*d_d1 - d_d2; + d_d2 = d_d1; + d_d1 = y; + d_processed++; + } + + gr_complex + goertzel::output() + { + gr_complex out((0.5*d_wr*d_d1-d_d2)/d_len, (d_wi*d_d1)/d_len); + d_d1 = 0.0; + d_d2 = 0.0; + d_processed = 0; + return out; + } + + } /* namespace fft */ +}/* namespace gr */ + diff --git a/gr-fft/lib/goertzel_fc_impl.cc b/gr-fft/lib/goertzel_fc_impl.cc new file mode 100644 index 000000000..ee214f24d --- /dev/null +++ b/gr-fft/lib/goertzel_fc_impl.cc @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 "goertzel_fc_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace fft { + + goertzel_fc::sptr goertzel_fc::make(int rate, int len, float freq) + { + return gnuradio::get_initial_sptr(new goertzel_fc_impl(rate, len, freq)); + } + + goertzel_fc_impl::goertzel_fc_impl(int rate, int len, float freq) + : gr_sync_decimator("goertzel_fc", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + len), + d_goertzel(rate, len, freq) + { + d_len = len; + d_rate = rate; + d_freq = freq; + } + + goertzel_fc_impl::~goertzel_fc_impl() + { + } + + void + goertzel_fc_impl::set_freq(float freq) + { + d_freq = freq; + d_goertzel.set_params(d_rate, d_len, d_freq); + } + + void + goertzel_fc_impl::set_rate(int rate) + { + d_rate = rate; + d_goertzel.set_params(d_rate, d_len, d_freq); + } + + int + goertzel_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++ = d_goertzel.batch(in); + in += d_len; + } + + return noutput_items; + } + + } /* namespace fft */ +} /* namespace gr */ diff --git a/gr-fft/lib/goertzel_fc_impl.h b/gr-fft/lib/goertzel_fc_impl.h new file mode 100644 index 000000000..426bc71f6 --- /dev/null +++ b/gr-fft/lib/goertzel_fc_impl.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_FFT_GOERTZEL_FC_IMPL_H +#define INCLUDED_FFT_GOERTZEL_FC_IMPL_H + +#include <fft/goertzel_fc.h> +#include <fft/goertzel.h> + +namespace gr { + namespace fft { + + class FFT_API goertzel_fc_impl : public goertzel_fc + { + private: + goertzel d_goertzel; + int d_len; + float d_freq; + int d_rate; + + public: + goertzel_fc_impl(int rate, int len, float freq); + + ~goertzel_fc_impl(); + + void set_freq(float freq); + void set_rate(int rate); + + float freq() { return d_freq; } + int rate() { return d_rate; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace fft */ +} /* namespace gr */ + +#endif /* INCLUDED_FFT_GOERTZEL_FC_IMPL_H */ + diff --git a/gr-fft/python/CMakeLists.txt b/gr-fft/python/CMakeLists.txt new file mode 100644 index 000000000..16c29e599 --- /dev/null +++ b/gr-fft/python/CMakeLists.txt @@ -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. + +######################################################################## +include(GrPython) + +GR_PYTHON_INSTALL( + FILES + __init__.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft + COMPONENT "fft_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-fft/python + ${CMAKE_BINARY_DIR}/gr-fft/swig + ) + set(GR_TEST_TARGET_DEPS gruel gnuradio-core gnuradio-fft) + 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-fft/python/__init__.py b/gr-fft/python/__init__.py new file mode 100644 index 000000000..0fa643e35 --- /dev/null +++ b/gr-fft/python/__init__.py @@ -0,0 +1,28 @@ +# +# 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-fft package. This package provides GNU Radio +processing blocks for FFT and related functions. +''' + +from fft_swig import * + diff --git a/gr-fft/python/qa_fft.py b/gr-fft/python/qa_fft.py new file mode 100755 index 000000000..1c45ac148 --- /dev/null +++ b/gr-fft/python/qa_fft.py @@ -0,0 +1,213 @@ +#!/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 fft_swig as fft +import sys +import random + +primes = (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53, + 59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131, + 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223, + 227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311) + + +class test_fft(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_001(self): + tb = gr.top_block() + fft_size = 32 + src_data = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + expected_result = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + op = fft.fft_vcc(fft_size, True, [], False) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, op, v2s, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + self.assert_fft_ok2(expected_result, result_data) + + def test_002(self): + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + op = fft.fft_vcc(fft_size, False, [], False) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, op, v2s, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + self.assert_fft_ok2(expected_result, result_data) + + def test_003(self): + # Same test as above, only use 2 threads + + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + nthreads = 2 + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + op = fft.fft_vcc(fft_size, False, [], False, nthreads) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, op, v2s, dst) + tb.run() + result_data = dst.data() + self.assert_fft_ok2(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_fft, "test_fft.xml") + diff --git a/gr-fft/python/qa_goertzel.py b/gr-fft/python/qa_goertzel.py new file mode 100755 index 000000000..27f9d370e --- /dev/null +++ b/gr-fft/python/qa_goertzel.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2006,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 +from math import pi, cos +import fft_swig as fft + +class test_goertzel(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def make_tone_data(self, rate, freq): + return [cos(2*pi*x*freq/rate) for x in range(rate)] + + def transform(self, src_data, rate, freq): + src = gr.vector_source_f(src_data, False) + dft = fft.goertzel_fc(rate, rate, freq) + dst = gr.vector_sink_c() + self.tb.connect(src, dft, dst) + self.tb.run() + return dst.data() + + def test_001(self): # Measure single tone magnitude + rate = 8000 + freq = 100 + bin = freq + src_data = self.make_tone_data(rate, freq) + expected_result = 0.5 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) + + def test_002(self): # Measure off frequency magnitude + rate = 8000 + freq = 100 + bin = freq/2 + src_data = self.make_tone_data(rate, freq) + expected_result = 0.0 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) + +if __name__ == '__main__': + gr_unittest.run(test_goertzel, "test_goertzel.xml") diff --git a/gr-fft/swig/CMakeLists.txt b/gr-fft/swig/CMakeLists.txt new file mode 100644 index 000000000..7ea41f220 --- /dev/null +++ b/gr-fft/swig/CMakeLists.txt @@ -0,0 +1,51 @@ +# 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_FFT_INCLUDE_DIRS} + ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} +) + +set(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i) +set(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../include/fft) + +set(GR_SWIG_LIBRARIES gnuradio-fft) + +GR_SWIG_MAKE(fft_swig fft_swig.i) + +GR_SWIG_INSTALL( + TARGETS fft_swig + DESTINATION ${GR_PYTHON_DIR}/gnuradio/fft + COMPONENT "fft_python" +) + +install( + FILES + fft_swig.i + ${CMAKE_CURRENT_BINARY_DIR}/fft_swig_doc.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "fft_swig" +) diff --git a/gr-fft/swig/fft_swig.i b/gr-fft/swig/fft_swig.i new file mode 100644 index 000000000..07fab34d4 --- /dev/null +++ b/gr-fft/swig/fft_swig.i @@ -0,0 +1,42 @@ +/* -*- 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 FFT_API + +%include "gnuradio.i" + +//load generated python docstrings +%include "fft_swig_doc.i" + +%{ +#include "fft/fft_vcc.h" +#include "fft/fft_vfc.h" +#include "fft/goertzel_fc.h" +%} + +%include "fft/fft_vcc.h" +%include "fft/fft_vfc.h" +%include "fft/goertzel_fc.h" + +GR_SWIG_BLOCK_MAGIC2(fft, fft_vcc); +GR_SWIG_BLOCK_MAGIC2(fft, fft_vfc); +GR_SWIG_BLOCK_MAGIC2(fft, goertzel_fc); diff --git a/gr-uhd/apps/uhd_fft b/gr-uhd/apps/uhd_fft index 8bb5e0d2b..7af2c5326 100755 --- a/gr-uhd/apps/uhd_fft +++ b/gr-uhd/apps/uhd_fft @@ -196,18 +196,18 @@ class app_top_block(stdgui2.std_top_block): callback=self.set_gain) try: - mboard_id = self.u.get_usrp_info().get("mboard_id").split(" ")[0] + mboard_id = self.u.get_usrp_info().get("mboard_id") mboard_serial = self.u.get_usrp_info().get("mboard_serial") if mboard_serial == "": mboard_serial = "no serial" - dboard_id = self.u.get_usrp_info().get("rx_id").split(" ")[0].split(",")[0] + dboard_subdev_name = self.u.get_usrp_info().get("rx_subdev_name") dboard_serial = self.u.get_usrp_info().get("rx_serial") if dboard_serial == "": dboard_serial = "no serial" subdev = self.u.get_subdev_spec() antenna = self.u.get_antenna() - usrp_config_val = "%s (%s), %s (%s, %s, %s)" % (mboard_id, mboard_serial, dboard_id, dboard_serial, subdev, antenna) + usrp_config_val = "%s (%s), %s (%s, %s, %s)" % (mboard_id, mboard_serial, dboard_subdev_name, dboard_serial, subdev, antenna) except: usrp_config_val = "Not implemented in this version." diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index 5fa881e42..8c69da1cc 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -110,11 +110,11 @@ class top_block(gr.top_block, pubsub): # Setup USRP Configuration value try: usrp_info = self._u.get_usrp_info() - mboard_id = usrp_info.get("mboard_id").split(" ")[0] + mboard_id = usrp_info.get("mboard_id") mboard_serial = usrp_info.get("mboard_serial") if mboard_serial == "": mboard_serial = "no serial" - dboard_id = usrp_info.get("tx_id").split(" ")[0].split(",")[0] + dboard_subdev_name = usrp_info.get("tx_subdev_name") dboard_serial = usrp_info.get("tx_serial") if dboard_serial == "": dboard_serial = "no serial" @@ -122,7 +122,7 @@ class top_block(gr.top_block, pubsub): antenna = self._u.get_antenna() desc_key_str = "Motherboard: %s [%s]\n" % (mboard_id, mboard_serial) - desc_key_str += "Daughterboard: %s [%s]\n" % (dboard_id, dboard_serial) + desc_key_str += "Daughterboard: %s [%s]\n" % (dboard_subdev_name, dboard_serial) desc_key_str += "Subdev: %s\n" % subdev desc_key_str += "Antenna: %s" % antenna except: diff --git a/gr-uhd/lib/gr_uhd_usrp_source.cc b/gr-uhd/lib/gr_uhd_usrp_source.cc index 8aa965401..99deb70c7 100644 --- a/gr-uhd/lib/gr_uhd_usrp_source.cc +++ b/gr-uhd/lib/gr_uhd_usrp_source.cc @@ -24,6 +24,8 @@ #include <stdexcept> #include <iostream> #include <boost/format.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/thread/condition_variable.hpp> #include <boost/make_shared.hpp> #include "gr_uhd_common.h" @@ -60,7 +62,8 @@ public: _nchan(std::max<size_t>(1, stream_args.channels.size())), _stream_now(_nchan == 1), _tag_now(false), - _start_time_set(false) + _start_time_set(false), + _is_streaming(false) { if (stream_args.cpu_format == "fc32") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_FLOAT32); if (stream_args.cpu_format == "sc16") _type = boost::make_shared<uhd::io_type_t>(uhd::io_type_t::COMPLEX_INT16); @@ -320,6 +323,13 @@ public: gr_vector_const_void_star &input_items, gr_vector_void_star &output_items ){ + boost::mutex::scoped_lock lock(_mutex); + + while (!_is_streaming) + { + _cond.wait(lock); + } + #ifdef GR_UHD_USE_STREAM_API //In order to allow for low-latency: //We receive all available packets without timeout. @@ -392,6 +402,9 @@ public: } bool start(void){ + boost::mutex::scoped_lock lock(_mutex); + _is_streaming = true; + #ifdef GR_UHD_USE_STREAM_API _rx_stream = _dev->get_rx_stream(_stream_args); _samps_per_packet = _rx_stream->get_max_num_samps(); @@ -436,6 +449,9 @@ public: } bool stop(void){ + boost::mutex::scoped_lock lock(_mutex); + _is_streaming = false; + _dev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); this->flush(); @@ -508,6 +524,10 @@ private: uhd::time_spec_t _start_time; bool _start_time_set; + + bool _is_streaming; + boost::condition_variable _cond; + boost::mutex _mutex; }; diff --git a/gr-wavelet/lib/CMakeLists.txt b/gr-wavelet/lib/CMakeLists.txt index f0d9068b7..d0c632800 100644 --- a/gr-wavelet/lib/CMakeLists.txt +++ b/gr-wavelet/lib/CMakeLists.txt @@ -35,6 +35,7 @@ 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 650299672..f11868395 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 82d083dea..2c5f433eb 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/grc/top_block_gui.py b/gr-wxgui/grc/top_block_gui.py index 333ccf1c1..479f55a30 100644 --- a/gr-wxgui/grc/top_block_gui.py +++ b/gr-wxgui/grc/top_block_gui.py @@ -48,7 +48,7 @@ class top_block_gui(gr.top_block): def SetIcon(self, *args, **kwargs): self._frame.SetIcon(*args, **kwargs) - def Run(self, start=True): + def Run(self, start=True, max_nouts=0): """ Setup the wx gui elements. Start the gr top block. @@ -69,6 +69,10 @@ class top_block_gui(gr.top_block): self._frame.Show(True) self._app.SetTopWindow(self._frame) #start flow graph - if start: self.start() + if start: + if max_nouts != 0: + self.start(max_nouts) + else: + self.start() #blocking main loop self._app.MainLoop() diff --git a/gr-wxgui/grc/wxgui_fftsink2.xml b/gr-wxgui/grc/wxgui_fftsink2.xml index ec5501838..74ee5b173 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 da6a8a3d1..8921e87f9 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 99c1cf6e1..fac83a4a3 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 6b268f6cb..dc31e84a1 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 a3a2b6451..4bcc36fd4 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 6775b7057..88215e039 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 5eaa76bc0..f1bc8f546 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 5af580339..2fdd0f20a 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 f2456241c..6a6bf6330 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 c78244f04..cd60104d7 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 c2c4e8df7..b69c5dda0 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/blocks/options.xml b/grc/blocks/options.xml index b27ea900c..1cf0b7707 100644 --- a/grc/blocks/options.xml +++ b/grc/blocks/options.xml @@ -125,6 +125,19 @@ else: self.stop(); self.wait()</callback> </option> </param> <param> + <name>Max Number of Output</name> + <key>max_nouts</key> + <value>0</value> + <type>int</type> + <hide>#if $generate_options() == 'hb' +all#slurp +#elif $max_nouts() +none#slurp +#else +part#slurp +#end if</hide> + </param> + <param> <name>Realtime Scheduling</name> <key>realtime_scheduling</key> <value></value> @@ -169,5 +182,9 @@ For example, an id of my_block will generate the file my_block.py and class my_b The category parameter determines the placement of the block in the block selection window. \ The category only applies when creating hier blocks. \ To put hier blocks into the root category, enter / for the category. + +The Max Number of Output is the maximum number of output items allowed for any block \ +in the flowgraph; to disable this set the max_nouts equal to 0.\ +Use this to adjust the maximum latency a flowgraph can exhibit. </doc> </block> diff --git a/grc/python/flow_graph.tmpl b/grc/python/flow_graph.tmpl index 0878be4ba..17feb01f6 100644 --- a/grc/python/flow_graph.tmpl +++ b/grc/python/flow_graph.tmpl @@ -244,12 +244,20 @@ if __name__ == '__main__': #end if #if $generate_options == 'wx_gui' tb = $(class_name)($(', '.join($params_eq_list))) + #if $flow_graph.get_option('max_nouts') + tb.Run($flow_graph.get_option('run'), $flow_graph.get_option('max_nouts')) + #else tb.Run($flow_graph.get_option('run')) + #end if #elif $generate_options == 'qt_gui' qapp = Qt.QApplication(sys.argv) tb = $(class_name)($(', '.join($params_eq_list))) #if $flow_graph.get_option('run') + #if $flow_graph.get_option('max_nouts') + tb.start($flow_graph.get_option('max_nouts')) + #else tb.start() + #end if #end if tb.show() qapp.exec_() @@ -258,11 +266,19 @@ if __name__ == '__main__': tb = $(class_name)($(', '.join($params_eq_list))) #set $run_options = $flow_graph.get_option('run_options') #if $run_options == 'prompt' + #if $flow_graph.get_option('max_nouts') + tb.start($flow_graph.get_option('max_nouts')) + #else tb.start() + #end if raw_input('Press Enter to quit: ') tb.stop() #elif $run_options == 'run' + #if $flow_graph.get_option('max_nouts') + tb.run($flow_graph.get_option('max_nouts')) + #else tb.run() + #end if #end if #end if #end if diff --git a/volk/CMakeLists.txt b/volk/CMakeLists.txt index fdde308ad..68385f974 100644 --- a/volk/CMakeLists.txt +++ b/volk/CMakeLists.txt @@ -54,10 +54,30 @@ SET(CROSSCOMPILE_MULTILIB ${CROSSCOMPILE_MULTILIB} CACHE STRING "Define \"true\" ######################################################################## # Dependencies setup ######################################################################## -find_package(PythonInterp REQUIRED PYTHON_EXECUTABLE) +include(GrPython) #sets PYTHON_EXECUTABLE and PYTHON_DASH_B +GR_PYTHON_CHECK_MODULE("python >= 2.5" sys "sys.version.split()[0] >= '2.5'" PYTHON_MIN_VER_FOUND) +GR_PYTHON_CHECK_MODULE("Cheetah >= 2.0.0" Cheetah "Cheetah.Version >= '2.0.0'" CHEETAH_FOUND) + +if(NOT PYTHON_MIN_VER_FOUND) + message(FATAL_ERROR "Python 2.5 or greater required to build VOLK") +endif() + +if(NOT CHEETAH_FOUND) + message(FATAL_ERROR "Cheetah templates required to build VOLK") +endif() + +set(Boost_ADDITIONAL_VERSIONS + "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39" + "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" + "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49" + "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" + "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59" + "1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64" + "1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69" +) find_package(Boost COMPONENTS unit_test_framework) -find_package(ORC) +find_package(ORC) ######################################################################## # Setup the package config file diff --git a/volk/apps/CMakeLists.txt b/volk/apps/CMakeLists.txt index 14291e5e3..175105a5a 100644 --- a/volk/apps/CMakeLists.txt +++ b/volk/apps/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011-2012 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 @@ -43,9 +43,8 @@ add_executable(volk_profile target_link_libraries(volk_profile volk ${Boost_LIBRARIES}) install( - PROGRAMS - ${CMAKE_BINARY_DIR}/apps/volk_profile - DESTINATION ${GR_RUNTIME_DIR} + TARGETS volk_profile + DESTINATION bin COMPONENT "volk" ) diff --git a/volk/apps/volk_profile.cc b/volk/apps/volk_profile.cc index 76b9f4031..0b4442108 100644 --- a/volk/apps/volk_profile.cc +++ b/volk/apps/volk_profile.cc @@ -16,6 +16,7 @@ int main(int argc, char *argv[]) { //VOLK_PROFILE(volk_16i_x5_add_quad_16i_x4_a, 1e-4, 2046, 10000, &results); //VOLK_PROFILE(volk_16i_branch_4_state_8_a, 1e-4, 2046, 10000, &results); + VOLK_PUPPET_PROFILE(volk_32fc_s32fc_rotatorpuppet_32fc_a, volk_32fc_s32fc_x2_rotator_32fc_a, 1e-2, (lv_32fc_t)lv_cmake(.95393, .3), 20460, 10000, &results); VOLK_PROFILE(volk_16ic_s32f_deinterleave_real_32f_a, 1e-5, 32768.0, 204600, 10000, &results); VOLK_PROFILE(volk_16ic_deinterleave_real_8i_a, 0, 0, 204600, 10000, &results); VOLK_PROFILE(volk_16ic_deinterleave_16i_x2_a, 0, 0, 204600, 10000, &results); diff --git a/volk/cmake/GrPython.cmake b/volk/cmake/GrPython.cmake new file mode 100644 index 000000000..eff9cbcdc --- /dev/null +++ b/volk/cmake/GrPython.cmake @@ -0,0 +1,233 @@ +# 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. + +if(DEFINED __INCLUDED_GR_PYTHON_CMAKE) + return() +endif() +set(__INCLUDED_GR_PYTHON_CMAKE TRUE) + +######################################################################## +# Setup the python interpreter: +# This allows the user to specify a specific interpreter, +# or finds the interpreter via the built-in cmake module. +######################################################################## +#this allows the user to override PYTHON_EXECUTABLE +if(PYTHON_EXECUTABLE) + + set(PYTHONINTERP_FOUND TRUE) + +#otherwise if not set, try to automatically find it +else(PYTHON_EXECUTABLE) + + #use the built-in find script + find_package(PythonInterp) + + #and if that fails use the find program routine + if(NOT PYTHONINTERP_FOUND) + find_program(PYTHON_EXECUTABLE NAMES python python2.7 python2.6 python2.5) + if(PYTHON_EXECUTABLE) + set(PYTHONINTERP_FOUND TRUE) + endif(PYTHON_EXECUTABLE) + endif(NOT PYTHONINTERP_FOUND) + +endif(PYTHON_EXECUTABLE) + +#make the path to the executable appear in the cmake gui +set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") + +#make sure we can use -B with python (introduced in 2.6) +if(PYTHON_EXECUTABLE) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -B -c "" + OUTPUT_QUIET ERROR_QUIET + RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT + ) + if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) + set(PYTHON_DASH_B "-B") + endif() +endif(PYTHON_EXECUTABLE) + +######################################################################## +# Check for the existence of a python module: +# - desc a string description of the check +# - mod the name of the module to import +# - cmd an additional command to run +# - have the result variable to set +######################################################################## +macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) + message(STATUS "") + message(STATUS "Python checking for ${desc}") + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c " +######################################### +try: import ${mod} +except: + try: ${mod} + except: exit(-1) +try: assert ${cmd} +except: exit(-1) +#########################################" + RESULT_VARIABLE ${have} + ) + if(${have} EQUAL 0) + message(STATUS "Python checking for ${desc} - found") + set(${have} TRUE) + else(${have} EQUAL 0) + message(STATUS "Python checking for ${desc} - not found") + set(${have} FALSE) + endif(${have} EQUAL 0) +endmacro(GR_PYTHON_CHECK_MODULE) + +######################################################################## +# Sets the python installation directory GR_PYTHON_DIR +######################################################################## +execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " +from distutils import sysconfig +print sysconfig.get_python_lib(plat_specific=True, prefix='') +" OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE +) +file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) + +######################################################################## +# Create an always-built target with a unique name +# Usage: GR_UNIQUE_TARGET(<description> <dependencies list>) +######################################################################## +function(GR_UNIQUE_TARGET desc) + file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib +unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] +print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" + OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) + add_custom_target(${_target} ALL DEPENDS ${ARGN}) +endfunction(GR_UNIQUE_TARGET) + +######################################################################## +# Install python sources (also builds and installs byte-compiled python) +######################################################################## +function(GR_PYTHON_INSTALL) + include(CMakeParseArgumentsCopy) + CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION;COMPONENT" "FILES;PROGRAMS" ${ARGN}) + + #################################################################### + if(GR_PYTHON_INSTALL_FILES) + #################################################################### + install(${ARGN}) #installs regular python files + + #create a list of all generated files + unset(pysrcfiles) + unset(pycfiles) + unset(pyofiles) + foreach(pyfile ${GR_PYTHON_INSTALL_FILES}) + get_filename_component(pyfile ${pyfile} ABSOLUTE) + list(APPEND pysrcfiles ${pyfile}) + + #determine if this file is in the source or binary directory + file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) + string(LENGTH "${source_rel_path}" source_rel_path_len) + file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) + string(LENGTH "${binary_rel_path}" binary_rel_path_len) + + #and set the generated path appropriately + if(${source_rel_path_len} GREATER ${binary_rel_path_len}) + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) + else() + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) + endif() + list(APPEND pycfiles ${pygenfile}c) + list(APPEND pyofiles ${pygenfile}o) + + #ensure generation path exists + get_filename_component(pygen_path ${pygenfile} PATH) + file(MAKE_DIRECTORY ${pygen_path}) + + endforeach(pyfile) + + #the command to generate the pyc files + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} + ) + + #the command to generate the pyo files + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} + COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} + ) + + #create install rule and add generated files to target list + set(python_install_gen_targets ${pycfiles} ${pyofiles}) + install(FILES ${python_install_gen_targets} + DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} + COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} + ) + + + #################################################################### + elseif(GR_PYTHON_INSTALL_PROGRAMS) + #################################################################### + file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) + + if (CMAKE_CROSSCOMPILING) + set(pyexe_native /usr/bin/env python) + endif() + + foreach(pyfile ${GR_PYTHON_INSTALL_PROGRAMS}) + get_filename_component(pyfile_name ${pyfile} NAME) + get_filename_component(pyfile ${pyfile} ABSOLUTE) + string(REPLACE "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" pyexefile "${pyfile}.exe") + list(APPEND python_install_gen_targets ${pyexefile}) + + get_filename_component(pyexefile_path ${pyexefile} PATH) + file(MAKE_DIRECTORY ${pyexefile_path}) + + add_custom_command( + OUTPUT ${pyexefile} DEPENDS ${pyfile} + COMMAND ${PYTHON_EXECUTABLE} -c + \"open('${pyexefile}', 'w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())\" + COMMENT "Shebangin ${pyfile_name}" + ) + + #on windows, python files need an extension to execute + get_filename_component(pyfile_ext ${pyfile} EXT) + if(WIN32 AND NOT pyfile_ext) + set(pyfile_name "${pyfile_name}.py") + endif() + + install(PROGRAMS ${pyexefile} RENAME ${pyfile_name} + DESTINATION ${GR_PYTHON_INSTALL_DESTINATION} + COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} + ) + endforeach(pyfile) + + endif() + + GR_UNIQUE_TARGET("pygen" ${python_install_gen_targets}) + +endfunction(GR_PYTHON_INSTALL) + +######################################################################## +# Write the python helper script that generates byte code files +######################################################################## +file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " +import sys, py_compile +files = sys.argv[1:] +srcs, gens = files[:len(files)/2], files[len(files)/2:] +for src, gen in zip(srcs, gens): + py_compile.compile(file=src, cfile=gen, doraise=True) +") diff --git a/volk/cmake/msvc/config.h b/volk/cmake/msvc/config.h new file mode 100644 index 000000000..43792c783 --- /dev/null +++ b/volk/cmake/msvc/config.h @@ -0,0 +1,58 @@ +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_CONFIG_H_ // [ +#define _MSC_CONFIG_H_ + +//////////////////////////////////////////////////////////////////////// +// enable inline functions for C code +//////////////////////////////////////////////////////////////////////// +#ifndef __cplusplus +# define inline __inline +#endif + +//////////////////////////////////////////////////////////////////////// +// signed size_t +//////////////////////////////////////////////////////////////////////// +#include <stddef.h> +typedef ptrdiff_t ssize_t; + +//////////////////////////////////////////////////////////////////////// +// rint functions +//////////////////////////////////////////////////////////////////////// +#include <math.h> +static inline long lrint(double x){return (long)(x > 0.0 ? x + 0.5 : x - 0.5);} +static inline long lrintf(float x){return (long)(x > 0.0f ? x + 0.5f : x - 0.5f);} +static inline long long llrint(double x){return (long long)(x > 0.0 ? x + 0.5 : x - 0.5);} +static inline long long llrintf(float x){return (long long)(x > 0.0f ? x + 0.5f : x - 0.5f);} +static inline double rint(double x){return (x > 0.0)? floor(x + 0.5) : ceil(x - 0.5);} +static inline float rintf(float x){return (x > 0.0f)? floorf(x + 0.5f) : ceilf(x - 0.5f);} + +//////////////////////////////////////////////////////////////////////// +// math constants +//////////////////////////////////////////////////////////////////////// +#define INFINITY HUGE_VAL + +# define M_E 2.7182818284590452354 /* e */ +# define M_LOG2E 1.4426950408889634074 /* log_2 e */ +# define M_LOG10E 0.43429448190325182765 /* log_10 e */ +# define M_LN2 0.69314718055994530942 /* log_e 2 */ +# define M_LN10 2.30258509299404568402 /* log_e 10 */ +# define M_PI 3.14159265358979323846 /* pi */ +# define M_PI_2 1.57079632679489661923 /* pi/2 */ +# define M_PI_4 0.78539816339744830962 /* pi/4 */ +# define M_1_PI 0.31830988618379067154 /* 1/pi */ +# define M_2_PI 0.63661977236758134308 /* 2/pi */ +# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +//////////////////////////////////////////////////////////////////////// +// random and srandom +//////////////////////////////////////////////////////////////////////// +#include <stdlib.h> +static inline long int random (void) { return rand(); } +static inline void srandom (unsigned int seed) { srand(seed); } + +#endif // _MSC_CONFIG_H_ ] diff --git a/volk/msvc/inttypes.h b/volk/cmake/msvc/inttypes.h index 0a1b60fc1..0a1b60fc1 100644 --- a/volk/msvc/inttypes.h +++ b/volk/cmake/msvc/inttypes.h diff --git a/volk/msvc/stdint.h b/volk/cmake/msvc/stdint.h index 108bc8982..108bc8982 100644 --- a/volk/msvc/stdint.h +++ b/volk/cmake/msvc/stdint.h diff --git a/volk/gen/archs.xml b/volk/gen/archs.xml index 59cc81cc5..2c9ab41a5 100644 --- a/volk/gen/archs.xml +++ b/volk/gen/archs.xml @@ -1,155 +1,183 @@ <!-- archs appear in order of significance for blind, de-facto version ordering --> <grammar> -<arch name="generic" type="all"> <!-- name and type are both required--> - <flag>none</flag> <!-- flag is the only required field--> +<arch name="generic"> <!-- name is required--> </arch> -<arch name="altivec" type="powerpc"> - <flag>maltivec</flag> +<arch name="altivec"> + <flag compiler="gnu">-maltivec</flag> <alignment>16</alignment> + <check name="has_ppc"></check> </arch> -<arch name="neon" type="arm"> - <flag>mfpu=neon,mfloat-abi=softfp,funsafe-math-optimizations</flag> +<arch name="neon"> + <flag compiler="gnu">-mfpu=neon</flag> + <flag compiler="gnu">-mfloat-abi=softfp</flag> + <flag compiler="gnu">-funsafe-math-optimizations</flag> <alignment>16</alignment> + <check name="has_neon"></check> </arch> -<arch name="32" type="x86" no_test="true" > - <flag>m32</flag> - <overrule>MD_SUBCPU</overrule> - <overrule_val>x86_64</overrule_val> +<arch name="32"> + <flag compiler="gnu">-m32</flag> </arch> -<arch name="64" type="x86"> - <op>0x80000001</op> - <reg>d</reg> - <shift>29</shift> - <flag>m64</flag> - <val>1</val> - <overrule>MD_SUBCPU</overrule> - <overrule_val>x86</overrule_val> +<arch name="64"> + <check name="check_extended_cpuid"> + <param>0x80000001</param> + </check> + <check name="cpuid_x86_bit"> <!-- checks to see if a bit is set --> + <param>3</param> <!-- eax, ebx, ecx, [edx] --> + <param>0x80000001</param> <!-- cpuid operation --> + <param>29</param> <!-- bit shift --> + </check> + <flag compiler="gnu">-m64</flag> </arch> -<arch name="3dnow" type="x86"> - <op>0x80000001</op> - <reg>d</reg> - <shift>31</shift> - <flag>m3dnow</flag> - <val>1</val> +<arch name="3dnow"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x80000001</param> + <param>31</param> + </check> + <flag compiler="gnu">-m3dnow</flag> <alignment>8</alignment> </arch> -<arch name="abm" type="x86"> - <val>1</val> - <op>0x80000001</op> - <reg>d</reg> - <shift>5</shift> - <flag>msse4.2</flag> +<arch name="abm"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x80000001</param> + <param>5</param> + </check> + <flag compiler="gnu">-msse4.2</flag> <alignment>16</alignment> </arch> -<arch name="popcount" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>23</shift> - <flag>mpopcnt</flag> -</arch> - -<arch name="mmx" type="x86"> - <val>1</val> - <op>1</op> - <reg>d</reg> - <shift>23</shift> - <flag>mmmx</flag> +<arch name="popcount"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>23</param> + </check> + <flag compiler="gnu">-mpopcnt</flag> + <flag compiler="msvc">/arch:AVX</flag> +</arch> + +<arch name="mmx"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x00000001</param> + <param>23</param> + </check> + <flag compiler="gnu">-mmmx</flag> + <flag compiler="msvc">/arch:SSE</flag> <alignment>8</alignment> </arch> - -<arch name="sse" type="x86"> - <val>1</val> - <op>1</op> - <reg>d</reg> - <shift>25</shift> - <flag>msse</flag> +<arch name="sse"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x00000001</param> + <param>25</param> + </check> + <flag compiler="gnu">-msse</flag> + <flag compiler="msvc">/arch:SSE</flag> <environment>_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);</environment> <include>xmmintrin.h</include> <alignment>16</alignment> </arch> - -<arch name="sse2" type="x86"> - <val>1</val> - <op>1</op> - <reg>d</reg> - <shift>26</shift> - <flag>msse2</flag> +<arch name="sse2"> + <check name="cpuid_x86_bit"> + <param>3</param> + <param>0x00000001</param> + <param>26</param> + </check> + <flag compiler="gnu">-msse2</flag> + <flag compiler="msvc">/arch:SSE2</flag> <alignment>16</alignment> </arch> -<arch name="orc" type="all"> - <flag>lorc-0.4</flag> - <overrule>LV_HAVE_ORC</overrule> - <overrule_val>no</overrule_val> +<arch name="orc"> </arch> -<arch name="sse3" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>0</shift> - <flag>msse3</flag> +<!-- it's here for overrule stuff. --> +<arch name="norc"> +</arch> + +<arch name="sse3"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>0</param> + </check> + <flag compiler="gnu">-msse3</flag> + <flag compiler="msvc">/arch:AVX</flag> <environment>_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);</environment> <include>pmmintrin.h</include> <alignment>16</alignment> </arch> -<arch name="ssse3" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>9</shift> - <flag>mssse3</flag> +<arch name="ssse3"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>9</param> + </check> + <flag compiler="gnu">-mssse3</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>16</alignment> </arch> -<arch name="sse4_a" type="x86"> - <val>1</val> - <op>0x80000001</op> - <reg>c</reg> - <shift>6</shift> - <flag>msse4a</flag> +<arch name="sse4_a"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x80000001</param> + <param>6</param> + </check> + <flag compiler="gnu">-msse4a</flag> <alignment>16</alignment> </arch> - -<arch name="sse4_1" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>19</shift> - <flag>msse4.1</flag> +<arch name="sse4_1"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>19</param> + </check> + <flag compiler="gnu">-msse4.1</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>16</alignment> </arch> -<arch name="sse4_2" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>20</shift> - <flag>msse4.2</flag> +<arch name="sse4_2"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>20</param> + </check> + <flag compiler="gnu">-msse4.2</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>16</alignment> </arch> -<arch name="avx" type="x86"> - <val>1</val> - <op>1</op> - <reg>c</reg> - <shift>28</shift> - <flag>mavx</flag> - <check>xgetbv</check> - <checkval>7</checkval> +<arch name="avx"> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>28</param> + </check> + <!-- check to make sure that xgetbv is enabled in OS --> + <check name="cpuid_x86_bit"> + <param>2</param> + <param>0x00000001</param> + <param>27</param> + </check> + <!-- check to see that the OS has enabled AVX --> + <check name="get_avx_enabled"></check> + <flag compiler="gnu">-mavx</flag> + <flag compiler="msvc">/arch:AVX</flag> <alignment>32</alignment> </arch> diff --git a/volk/gen/compilers.xml b/volk/gen/compilers.xml deleted file mode 100644 index 005eda2aa..000000000 --- a/volk/gen/compilers.xml +++ /dev/null @@ -1,30 +0,0 @@ -<!-- compilers remap gcc-specific information from archs.xml to specific compiler cases--> -<grammar> - -<compiler name="MSVC"> - <!-- remap the following flags to SSE --> - <remap name="mmmx">arch:SSE</remap> - <remap name="msse">arch:SSE</remap> - - <!-- remap the following flags to SSE2 --> - <remap name="msse2">arch:SSE2</remap> - - <!-- remap the following flags to AVX --> - <remap name="msse3">arch:AVX</remap> - <remap name="mssse3">arch:AVX</remap> - <remap name="msse4.1">arch:AVX</remap> - <remap name="msse4.2">arch:AVX</remap> - <remap name="mpopcnt">arch:AVX</remap> - <remap name="mavx">arch:AVX</remap> - - <prefix>/</prefix> -</compiler> - -<compiler name="GNU"> - <prefix>-</prefix> -</compiler> - - - - -</grammar> diff --git a/volk/gen/machines.xml b/volk/gen/machines.xml index 9c19c91c6..8e3c9c8c2 100644 --- a/volk/gen/machines.xml +++ b/volk/gen/machines.xml @@ -1,64 +1,51 @@ <grammar> <machine name="generic"> -<archs>generic</archs> +<archs>generic orc|</archs> </machine> <!-- <machine name="mmx"> -<archs>generic 32|64 mmx</archs> +<archs>generic 32|64 mmx orc|</archs> </machine> <machine name="sse"> -<archs>generic 32|64 mmx sse</archs> +<archs>generic 32|64| mmx sse orc|</archs> </machine> --> -<!-- -Create an SSE2 and AVX only machine (without 64/32 inline assembly support). -This machine is intended to support the MSVC compiler on x86/amd64. -The MSVC compiler has intrinsic support for SSE, SSE2, AVX -however it does not support the gcc style inline assembly. ---> - <machine name="neon"> -<archs>generic neon</archs> -</machine> - -<machine name="sse2_only"> -<archs>generic mmx sse sse2</archs> +<archs>generic neon orc|</archs> </machine> +<!-- trailing | bar means generate without either for MSVC --> <machine name="sse2"> -<archs>generic 32|64 mmx sse sse2</archs> +<archs>generic 32|64| mmx sse sse2 orc|</archs> </machine> <machine name="sse3"> -<archs>generic 32|64 mmx sse sse2 sse3</archs> +<archs>generic 32|64 mmx sse sse2 sse3 orc|</archs> </machine> <machine name="ssse3"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3</archs> +<archs>generic 32|64 mmx sse sse2 sse3 ssse3 orc|</archs> </machine> <machine name="sse4_a"> -<archs>generic 32|64 mmx sse sse2 sse3 sse4_a popcount</archs> +<archs>generic 32|64 mmx sse sse2 sse3 sse4_a popcount orc|</archs> </machine> <machine name="sse4_1"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1</archs> +<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 orc|</archs> </machine> <machine name="sse4_2"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount</archs> +<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount orc|</archs> </machine> +<!-- trailing | bar means generate without either for MSVC --> <machine name="avx"> -<archs>generic 32|64 mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx</archs> -</machine> - -<machine name="avx_only"> -<archs>generic mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx</archs> +<archs>generic 32|64| mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 popcount avx orc|</archs> </machine> <machine name="altivec"> diff --git a/volk/gen/make_c.py b/volk/gen/make_c.py deleted file mode 100644 index 233cb85c2..000000000 --- a/volk/gen/make_c.py +++ /dev/null @@ -1,88 +0,0 @@ -# -# Copyright 2010-2011 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/>. -# - -from volk_regexp import * -import string - -#ok todo list: -#put n_archs into the info struct so it doesn't have to be arch_defs[0]. - -def make_c(machines, archs, functions, arched_arglist, my_arglist): - tempstring = r""" -// This file is automatically generated by make_c.py. -// Do not edit this file. -""" - tempstring += """ -#include <volk/volk_common.h> -#include "volk_machines.h" -#include <volk/volk_typedefs.h> -#include <volk/volk_cpu.h> -#include "volk_rank_archs.h" -#include <volk/volk.h> -#include <stdio.h> -#include <string.h> - -""" - -#OK here's the deal. the .h prototypes the functions. the .c impls them as fptrs, can use p_whatever. -#also .c impls the get_machine call -#also .c impls the default call for each fn - -#here do static fn get arch - tempstring += r""" -struct volk_machine *get_machine(void) { - extern struct volk_machine *volk_machines[]; - extern unsigned int n_volk_machines; - static struct volk_machine *machine = NULL; - - if(machine != NULL) return machine; - else { - unsigned int max_score = 0; - unsigned int i; - for(i=0; i<n_volk_machines; i++) { - if(!(volk_machines[i]->caps & (~volk_get_lvarch()))) { - if(volk_machines[i]->caps > max_score) { - max_score = volk_machines[i]->caps; - machine = volk_machines[i]; - } - } - } - printf("Using Volk machine: %s\n", machine->name); - return machine; - } -} - -unsigned int volk_get_alignment(void) { - return get_machine()->alignment; -} - -""" - - for i in range(len(functions)): - tempstring += "void get_" + functions[i] + replace_arch.sub("", arched_arglist[i]) + "\n" - tempstring += " %s = get_machine()->%s_archs[volk_rank_archs(get_machine()->%s_indices, get_machine()->%s_arch_defs, get_machine()->%s_n_archs, get_machine()->%s_name, volk_get_lvarch())];\n" % (functions[i], functions[i], functions[i], functions[i], functions[i], functions[i]) - tempstring += " %s(%s);\n}\n\n" % (functions[i], my_arglist[i]) - tempstring += replace_volk.sub("p", functions[i]) + " " + functions[i] + " = &get_" + functions[i] + ";\n\n" - tempstring += "void %s_manual%s\n" % (functions[i], arched_arglist[i]) - tempstring += " get_machine()->%s_archs[get_index(get_machine()->%s_indices, get_machine()->%s_n_archs, arch)](%s);\n}\n" % (functions[i], functions[i], functions[i], my_arglist[i]) - tempstring += "struct volk_func_desc %s_get_func_desc(void) {\n" % (functions[i]) - tempstring += " struct volk_func_desc desc = {get_machine()->%s_indices, get_machine()->%s_arch_defs, get_machine()->%s_n_archs};\n" % (functions[i], functions[i], functions[i]) - tempstring += " return desc;\n}\n" - - return tempstring - - diff --git a/volk/gen/make_config_fixed.py b/volk/gen/make_config_fixed.py deleted file mode 100644 index 96f20b6b2..000000000 --- a/volk/gen/make_config_fixed.py +++ /dev/null @@ -1,21 +0,0 @@ -from xml.dom import minidom - -def make_config_fixed(dom) : - tempstring = ""; - tempstring = tempstring +'/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '\n#ifndef INCLUDED_VOLK_CONFIG_FIXED_H'; - tempstring = tempstring + '\n#define INCLUDED_VOLK_CONFIG_FIXED_H'; - tempstring = tempstring + '\n\n'; - enum_counter = 0; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + '#define LV_' + arch.swapcase() + " " + str(enum_counter) + '\n'; - enum_counter = enum_counter + 1; - tempstring = tempstring + '\n\n'; - - tempstring = tempstring + "#endif /*INCLUDED_VOLK_CONFIG_FIXED*/\n" - - return tempstring; - - - diff --git a/volk/gen/make_config_in.py b/volk/gen/make_config_in.py deleted file mode 100644 index d29680af2..000000000 --- a/volk/gen/make_config_in.py +++ /dev/null @@ -1,13 +0,0 @@ -from xml.dom import minidom - -def make_config_in(dom) : - tempstring = ""; - tempstring = tempstring +'/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '\n\n'; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + '#undef LV_HAVE_' + arch.swapcase() + '\n'; - tempstring = tempstring + '\n'; - - return tempstring diff --git a/volk/gen/make_cpuid_c.py b/volk/gen/make_cpuid_c.py deleted file mode 100644 index 005fc2b19..000000000 --- a/volk/gen/make_cpuid_c.py +++ /dev/null @@ -1,283 +0,0 @@ -#!/usr/bin/env python -# -# 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. -# - -from xml.dom import minidom - -HEADER_TEMPL = """\ -/*this file is auto_generated by volk_register.py*/ - -#include <volk/volk_cpu.h> -#include <volk/volk_config_fixed.h> - -struct VOLK_CPU volk_cpu; - -#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) -# define VOLK_CPU_x86 -#endif - -#if defined(VOLK_CPU_x86) - -//implement get cpuid for gcc compilers using a copy of cpuid.h -#if defined(__GNUC__) -#include <gcc_x86_cpuid.h> -#define cpuid_x86(op, r) __get_cpuid(op, (unsigned int *)r+0, (unsigned int *)r+1, (unsigned int *)r+2, (unsigned int *)r+3) - - /* Return Intel AVX extended CPU capabilities register. - * This function will bomb on non-AVX-capable machines, so - * check for AVX capability before executing. - */ - #if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 - static inline unsigned long long _xgetbv(unsigned int index){ - unsigned int eax, edx; - __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); - return ((unsigned long long)edx << 32) | eax; - } - #define __xgetbv() _xgetbv(0) - #else - #define __xgetbv() 0 - #endif - -//implement get cpuid for MSVC compilers using __cpuid intrinsic -#elif defined(_MSC_VER) -#include <intrin.h> -#define cpuid_x86(op, r) __cpuid(r, op) - - #if defined(_XCR_XFEATURE_ENABLED_MASK) - #define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) - #else - #define __xgetbv() 0 - #endif - -#else -#error "A get cpuid for volk is not available on this compiler..." -#endif - -static inline unsigned int cpuid_eax(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[0]; -} - -static inline unsigned int cpuid_ebx(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[1]; -} - -static inline unsigned int cpuid_ecx(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[2]; -} - -static inline unsigned int cpuid_edx(unsigned int op) { - int regs[4]; - cpuid_x86 (op, regs); - return regs[3]; -} - -static inline unsigned int xgetbv(void) { - //check to make sure that xgetbv is enabled in OS - int xgetbv_enabled = cpuid_ecx(1) >> 27 & 0x01; - if(xgetbv_enabled == 0) return 0; - return __xgetbv(); -} -#endif - -""" - -def make_cpuid_c(dom) : - tempstring = HEADER_TEMPL; - - for domarch in dom: - if str(domarch.attributes["type"].value) == "x86": - if "no_test" in domarch.attributes.keys(): - no_test = str(domarch.attributes["no_test"].value); - if no_test == "true": - no_test = True; - else: - no_test = False; - else: - no_test = False; - arch = str(domarch.attributes["name"].value) - op = domarch.getElementsByTagName("op") - if op: - op = str(op[0].firstChild.data) - reg = domarch.getElementsByTagName("reg") - if reg: - reg = str(reg[0].firstChild.data) - shift = domarch.getElementsByTagName("shift") - if shift: - shift = str(shift[0].firstChild.data) - val = domarch.getElementsByTagName("val") - if val: - val = str(val[0].firstChild.data) - check = domarch.getElementsByTagName("check") - if check: - check = str(check[0].firstChild.data) - checkval = domarch.getElementsByTagName("checkval") - if checkval: - checkval = str(checkval[0].firstChild.data) - - if no_test: - tempstring = tempstring + """\ -int i_can_has_%s () { -#if defined(VOLK_CPU_x86) - return 1; -#else - return 0; -#endif -} - -""" % (arch) - - elif op == "1": - tempstring = tempstring + """\ -int i_can_has_%s () { -#if defined(VOLK_CPU_x86) - unsigned int e%sx = cpuid_e%sx (%s); - int hwcap = (((e%sx >> %s) & 1) == %s); -""" % (arch, reg, reg, op, reg, shift, val) - - if check and checkval: - tempstring += """\ - if (hwcap == 0) return 0; - hwcap &= (%s() == %s); -""" % (check, checkval) - - tempstring += """\ - return hwcap; -#else - return 0; -#endif -} - -""" - - elif op == "0x80000001": - tempstring = tempstring + """\ -int i_can_has_%s () { -#if defined(VOLK_CPU_x86) - unsigned int extended_fct_count = cpuid_eax(0x80000000); - if (extended_fct_count < 0x80000001) - return %s^1; - unsigned int extended_features = cpuid_e%sx (%s); - return ((extended_features >> %s) & 1) == %s; -#else - return 0; -#endif -} - -""" % (arch, val, reg, op, shift, val) - - elif str(domarch.attributes["type"].value) == "powerpc": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -int i_can_has_%s () { -#ifdef __PPC__ - return 1; -#else - return 0; -#endif -} - -""" % (arch) - - elif str(domarch.attributes["type"].value) == "arm": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -#if defined(__arm__) && defined(__linux__) -#include <asm/hwcap.h> -#include <linux/auxvec.h> -#include <stdio.h> -#define LOOK_FOR_NEON -#endif - -int i_can_has_%s () { -//it's linux-specific, but if you're compiling libvolk for NEON -//on Windows you have other problems - -#ifdef LOOK_FOR_NEON - FILE *auxvec_f; - unsigned long auxvec[2]; - unsigned int found_neon = 0; - auxvec_f = fopen("/proc/self/auxv", "rb"); - if(!auxvec_f) return 0; - - //so auxv is basically 32b of ID and 32b of value - //so it goes like this - while(!found_neon && auxvec_f) { - fread(auxvec, sizeof(unsigned long), 2, auxvec_f); - if((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_NEON)) - found_neon = 1; - } - - fclose(auxvec_f); - return found_neon; - -#else - return 0; -#endif -} - -""" % (arch) - - elif str(domarch.attributes["type"].value) == "all": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -int i_can_has_%s () { - return 1; -} - -""" % (arch) - else: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + """\ -int i_can_has_%s () { - return 0; -} - -""" % (arch) - - tempstring = tempstring + "void volk_cpu_init() {\n"; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " volk_cpu.has_" + arch + " = &i_can_has_" + arch + ";\n" - tempstring = tempstring + "}\n\n" - - tempstring = tempstring + "unsigned int volk_get_lvarch() {\n"; - tempstring = tempstring + " unsigned int retval = 0;\n" - tempstring = tempstring + " volk_cpu_init();\n" - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " retval += volk_cpu.has_" + arch + "() << LV_" + arch.swapcase() + ";\n" - tempstring = tempstring + " return retval;\n" - tempstring = tempstring + "}\n\n" - - return tempstring; - - - - - - - diff --git a/volk/gen/make_cpuid_h.py b/volk/gen/make_cpuid_h.py deleted file mode 100644 index 1aa783781..000000000 --- a/volk/gen/make_cpuid_h.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -# 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. -# - -from xml.dom import minidom - -def make_cpuid_h(dom) : - tempstring = ""; - tempstring = tempstring +'/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring +'\n#ifndef INCLUDED_VOLK_CPU_H'; - tempstring = tempstring +'\n#define INCLUDED_VOLK_CPU_H\n\n'; - tempstring = tempstring + "#include <volk/volk_common.h>\n\n"; - tempstring = tempstring + '__VOLK_DECL_BEGIN\n'; - tempstring = tempstring + '\n' - - tempstring = tempstring + "struct VOLK_CPU {\n" - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " int (*has_" + arch + ") ();\n"; - tempstring = tempstring + "};\n\n"; - tempstring = tempstring + "extern struct VOLK_CPU volk_cpu;\n\n"; - - tempstring = tempstring + "void volk_cpu_init ();\n" - tempstring = tempstring + "unsigned int volk_get_lvarch ();\n" - - tempstring = tempstring + "\n"; - tempstring = tempstring + "__VOLK_DECL_END\n"; - tempstring = tempstring + "#endif /*INCLUDED_VOLK_CPU_H*/\n" - - return tempstring; diff --git a/volk/gen/make_each_machine_c.py b/volk/gen/make_each_machine_c.py deleted file mode 100644 index 535578859..000000000 --- a/volk/gen/make_each_machine_c.py +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright 2010-2011 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/>. -# - -from volk_regexp import * -import string - -def _make_each_machine_struct(machine_name, archs, functions, fcountlist, taglist, alignment): - - #make the machine fcountlist and taglist a subset given the archs list - machine_fcountlists = list() - machine_taglists = list() - for i in range(len(fcountlist)): - machine_fcountlist = list() - machine_taglist = list() - for j in range(len(fcountlist[i])): - if len(set(archs).intersection(map(str.lower, fcountlist[i][j]))) == len(fcountlist[i][j]): - machine_fcountlist.append(fcountlist[i][j]) - machine_taglist.append(taglist[i][j]) - machine_fcountlists.append(machine_fcountlist) - machine_taglists.append(machine_taglist) - - #create the volk machine struct for this machine file - tempstring = "" - tempstring += "struct volk_machine volk_machine_" + machine_name + " = {\n" - tempstring += " " + ' | '.join(["(1 << LV_" + arch.swapcase() + ")" for arch in archs]) + ",\n" - tempstring += " \"%s\",\n"%machine_name - tempstring += " %s,\n"%alignment - - #fill in the description for each function - for i in range(len(functions)): - tempstring += " \"%s\",\n"%functions[i] - tempstring += " {%s},\n"%(', '.join(['"%s"'%tag for tag in machine_taglists[i]])) - tempstring += " {%s},\n"%(', '.join([' | '.join(['(1 << LV_%s)'%fc for fc in fcount]) for fcount in machine_fcountlists[i]])) - tempstring += " {%s},\n"%(', '.join(['%s_%s'%(functions[i], tag) for tag in machine_taglists[i]])) - tempstring += " %d,\n"%len(machine_taglists[i]) - - tempstring = strip_trailing(tempstring, ",") - tempstring += "};\n" - return tempstring - -def make_each_machine_c(machine_name, archs, functions, fcountlist, taglist, alignment): - tempstring = r""" -// This file is automatically generated by make_each_machine_c.py. -// Do not edit this file. -""" - for arch in archs: - tempstring += "#define LV_HAVE_" + arch.swapcase() + " 1\n" - - tempstring += """ -#include <volk/volk_common.h> -#include "volk_machines.h" -#include <volk/volk_config_fixed.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -""" - for func in functions: - tempstring += "#include <volk/" + func + ".h>\n" - tempstring += "\n\n" - - tempstring += """ -#ifdef LV_HAVE_ORC -%s -#else -%s -#endif -"""%( - _make_each_machine_struct(machine_name, archs+["orc"], functions, fcountlist, taglist, alignment), - _make_each_machine_struct(machine_name, archs, functions, fcountlist, taglist, alignment) -) - - return tempstring - - diff --git a/volk/gen/make_environment_init_c.py b/volk/gen/make_environment_init_c.py deleted file mode 100644 index 6186162ee..000000000 --- a/volk/gen/make_environment_init_c.py +++ /dev/null @@ -1,32 +0,0 @@ -from xml.dom import minidom - -def make_environment_init_c(dom) : - tempstring = ""; - tempstring = tempstring + "/*this file is auto_generated by volk_register.py*/\n\n"; - tempstring = tempstring + "#include<volk/volk_environment_init.h>\n" - for domarch in dom: - arch = str(domarch.attributes["name"].value); - incs = domarch.getElementsByTagName("include"); - for inc in incs: - my_inc = str(inc.firstChild.data); - tempstring = tempstring + "#ifdef LV_HAVE_" + arch.swapcase() + "\n"; - tempstring = tempstring + "#include<" + my_inc + ">\n"; - tempstring = tempstring + "#endif\n" - tempstring = tempstring + '\n\n'; - tempstring = tempstring + "void volk_environment_init(){\n" - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - envs = domarch.getElementsByTagName("environment"); - for env in envs: - cmd = str(env.firstChild.data); - tempstring = tempstring + "#ifdef LV_HAVE_" + arch.swapcase() + "\n"; - tempstring = tempstring + " " + cmd + "\n"; - tempstring = tempstring + "#endif\n" - - tempstring = tempstring + "}\n"; - return tempstring; - - - - diff --git a/volk/gen/make_environment_init_h.py b/volk/gen/make_environment_init_h.py deleted file mode 100644 index 0b0f35d61..000000000 --- a/volk/gen/make_environment_init_h.py +++ /dev/null @@ -1,18 +0,0 @@ -from xml.dom import minidom - -def make_environment_init_h() : - tempstring = ""; - tempstring = tempstring + "/*this file is auto_generated by volk_register.py*/\n\n"; - tempstring = tempstring + "#ifndef INCLUDE_LIBVECTOR_ENVIRONMENT_INIT_H\n"; - tempstring = tempstring + "#define INCLUDE_LIBVECTOR_ENVIRONMENT_INIT_H\n"; - tempstring = tempstring + "\n"; - tempstring = tempstring + "#include <volk/volk_common.h>\n\n"; - tempstring = tempstring + "__VOLK_DECL_BEGIN\n"; - tempstring = tempstring + "void volk_environment_init();\n"; - tempstring = tempstring + "__VOLK_DECL_END\n"; - tempstring = tempstring + "#endif\n" - return tempstring; - - - - diff --git a/volk/gen/make_h.py b/volk/gen/make_h.py deleted file mode 100644 index cf8987c39..000000000 --- a/volk/gen/make_h.py +++ /dev/null @@ -1,38 +0,0 @@ -from xml.dom import minidom -from volk_regexp import * - -def make_h(funclist, arched_arglist) : - tempstring = ""; - tempstring = tempstring + '/*this file is auto generated by make_h.py*/\n'; - - tempstring = tempstring + '\n#ifndef INCLUDED_VOLK_RUNTIME'; - tempstring = tempstring + '\n#define INCLUDED_VOLK_RUNTIME'; - tempstring = tempstring + '\n\n#include<volk/volk_typedefs.h>\n'; - tempstring = tempstring + '#include<volk/volk_config_fixed.h>\n'; - tempstring = tempstring + '#include<volk/volk_common.h>\n'; - tempstring = tempstring + '#include<volk/volk_complex.h>\n'; - tempstring = tempstring + '__VOLK_DECL_BEGIN\n'; - - tempstring = tempstring + '\n'; - - tempstring += """ -struct volk_func_desc { - const char **indices; - const int *arch_defs; - const int n_archs; -}; - -VOLK_API unsigned int volk_get_alignment(void); - -""" - for i in range(len(funclist)): - tempstring += "extern VOLK_API " + replace_volk.sub("p", funclist[i]) + " " + funclist[i] + ";\n" - tempstring += "extern VOLK_API void %s_manual%s;\n" % (funclist[i], arched_arglist[i]) - tempstring = strip_trailing(tempstring, " {") - tempstring += "extern VOLK_API struct volk_func_desc %s_get_func_desc(void);\n" % (funclist[i]) - - tempstring = tempstring + '__VOLK_DECL_END\n'; - tempstring = tempstring + "#endif /*INCLUDED_VOLK_RUNTIME*/\n"; - - return tempstring; - diff --git a/volk/gen/make_machines_c.py b/volk/gen/make_machines_c.py deleted file mode 100644 index f19da4ae4..000000000 --- a/volk/gen/make_machines_c.py +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright 2010-2011 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/>. -# - -from volk_regexp import * - -def make_machines_c(machines): - tempstring = r""" -// This file is automatically generated by make_machines_c.py. -// Do not edit this file. - -#include <volk/volk_common.h> -#include <volk/volk_typedefs.h> -#include "volk_machines.h" - -struct volk_machine *volk_machines[] = { -""" - for machine in machines: - tempstring += """#if LV_MACHINE_""" + machine.swapcase() + "\n" - tempstring += "&volk_machine_" + machine - tempstring += "," - tempstring += "\n#endif\n" - - tempstring += r""" -}; -unsigned int n_volk_machines = sizeof(volk_machines)/sizeof(*volk_machines); -""" - return tempstring diff --git a/volk/gen/make_machines_h.py b/volk/gen/make_machines_h.py deleted file mode 100644 index d2374120b..000000000 --- a/volk/gen/make_machines_h.py +++ /dev/null @@ -1,59 +0,0 @@ -# -# Copyright 2010-2011 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/>. -# - -from volk_regexp import * - -def make_machines_h(functions, machines, archs): - tempstring = r""" -// This file is automatically generated by make_machines_h.py. -// Do not edit this file. - -#ifndef INCLUDED_LIBVOLK_MACHINES_H -#define INCLUDED_LIBVOLK_MACHINES_H - -#include <volk/volk_common.h> -#include <volk/volk_typedefs.h> - -__VOLK_DECL_BEGIN - -struct volk_machine { - const unsigned int caps; //capabilities (i.e., archs compiled into this machine, in the volk_get_lvarch format) - const char *name; - const unsigned int alignment; //the maximum byte alignment required for functions in this library -""" - for function in functions: - tempstring += " const char *%s_name;\n"%function - tempstring += " const char *%s_indices[%d];\n"%(function, len(archs)) - tempstring += " const int %s_arch_defs[%d];\n"%(function, len(archs)) - tempstring += " const %s %s_archs[%d];\n"%(replace_volk.sub("p", function), function, len(archs)) - tempstring += " const int %s_n_archs;\n"%function - - tempstring += r"""}; - -""" - for machine in machines: - tempstring += """#if LV_MACHINE_""" + machine.swapcase() + "\n" - tempstring += "extern struct volk_machine volk_machine_" + machine + ";\n" - tempstring += """#endif\n""" - - tempstring += r""" - -__VOLK_DECL_END - -#endif //INCLUDED_LIBVOLK_MACHINES_H""" - - return tempstring diff --git a/volk/gen/make_makefile_am.py b/volk/gen/make_makefile_am.py deleted file mode 100644 index 880ce4094..000000000 --- a/volk/gen/make_makefile_am.py +++ /dev/null @@ -1,123 +0,0 @@ -# -# Copyright 2010-2011 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/>. -# - -from xml.dom import minidom - -def make_makefile_am(dom, machines, archflags_dict): - tempstring = r""" -# This file is automatically generated by make_makefile_am.py. -# Do not edit this file. - -include $(top_srcdir)/Makefile.common - -AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) \ - -I$(top_gendir)/include \ - -I$(top_srcdir)/include \ - -Dvolk_EXPORTS \ - -fvisibility=hidden \ - $(WITH_INCLUDES) - -lib_LTLIBRARIES = \ - libvolk.la - -EXTRA_DIST = \ - volk_rank_archs.h \ - gcc_x86_cpuid.h - -# ---------------------------------------------------------------- -# The main library -# ---------------------------------------------------------------- - -libvolk_la_SOURCES = \ - $(platform_CODE) \ - $(top_gendir)/lib/volk.c \ - $(top_gendir)/lib/volk_cpu.c \ - volk_rank_archs.c \ - volk_prefs.c \ - $(top_gendir)/lib/volk_machines.c - -if LV_HAVE_ORC -volk_orc_CFLAGS = -DLV_HAVE_ORC=1 -volk_orc_LDFLAGS = $(ORC_LDFLAGS) -lorc-0.4 -volk_orc_LIBADD = ../orc/libvolk_orc.la -else -volk_orc_CFLAGS = -volk_orc_LDFLAGS = -volk_orc_LIBADD = -endif - -libvolk_la_CPPFLAGS = $(AM_CPPFLAGS) $(volk_orc_CFLAGS) -libvolk_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 $(volk_orc_LDFLAGS) -libvolk_la_LIBADD = $(volk_orc_LIBADD) - -noinst_LTLIBRARIES = - -""" - - #here be dragons - for machine_name in machines: - tempstring += "if LV_MACHINE_" + machine_name.swapcase() + "\n" - tempstring += "libvolk_" + machine_name + "_la_SOURCES = $(top_gendir)/lib/volk_machine_" + machine_name + ".c\n" - tempstring += "libvolk_" + machine_name + "_la_CPPFLAGS = -I$(top_srcdir)/include -I$(top_gendir)/include $(volk_orc_CFLAGS) " - for arch in machines[machine_name]: - if archflags_dict[arch] != "none": - tempstring += "-" + archflags_dict[arch] + " " - - tempstring += "\nnoinst_LTLIBRARIES += libvolk_" + machine_name + ".la " - tempstring += "\nlibvolk_la_LIBADD += libvolk_" + machine_name + ".la\n" - tempstring += "libvolk_la_CPPFLAGS += -DLV_MACHINE_" + machine_name.swapcase() + " \n" - tempstring += "endif\n" - - - tempstring += r""" - -# ---------------------------------------------------------------- -# The QA library. Note libvolk.la in LIBADD -# ---------------------------------------------------------------- -#libvolk_qa_la_SOURCES = \ -# qa_utils.cc - -#libvolk_qa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 -lboost - -#libvolk_qa_la_LIBADD = \ -# libvolk.la \ -# libvolk_runtime.la - -# ---------------------------------------------------------------- -# headers that don't get installed -# ---------------------------------------------------------------- -noinst_HEADERS = \ - $(top_gendir)/lib/volk_init.h \ - $(top_gendir)/lib/volk_machines.h \ - $(top_gendir)/lib/volk_environment_init.h \ - qa_utils.h - -# ---------------------------------------------------------------- -# Our test program -# ---------------------------------------------------------------- -noinst_PROGRAMS = \ - testqa - -testqa_SOURCES = testqa.cc qa_utils.cc -testqa_CPPFLAGS = -DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN $(AM_CPPFLAGS) -testqa_LDFLAGS = $(BOOST_UNIT_TEST_FRAMEWORK_LIB) -testqa_LDADD = \ - libvolk.la -""" - - - return tempstring diff --git a/volk/gen/make_proccpu_sim.py b/volk/gen/make_proccpu_sim.py deleted file mode 100644 index e2c8123e5..000000000 --- a/volk/gen/make_proccpu_sim.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -# 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. -# - -from xml.dom import minidom - -def make_proccpu_sim(dom) : - tempstring = ""; - tempstring = tempstring + "/*this file is auto_generated by volk_register.py*/\n\n"; - tempstring = tempstring + "#include <volk/volk_cpu.h>\n" - tempstring = tempstring + "#include <stdio.h>\n" - tempstring = tempstring + "\n\n" - - tempstring = tempstring + "void test_append(char* buf, int val, char* newkey){\n"; - tempstring = tempstring + " if(val==1){\n"; - tempstring = tempstring + " sprintf(buf, \"%s %s\", buf, newkey);\n"; - tempstring = tempstring + " }\n"; - tempstring = tempstring + "}\n"; - tempstring = tempstring + "\n\n"; - - tempstring = tempstring + "int main() {\n"; - tempstring = tempstring + " volk_cpu_init();\n"; - tempstring = tempstring + " char buf[2048];\n"; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " test_append(buf, volk_cpu.has_" + arch + "(), \"" + arch + "\");\n" - tempstring = tempstring + " printf(\"%s\\n\", buf);\n" - tempstring = tempstring + "}\n" - return tempstring; diff --git a/volk/gen/make_set_simd.py b/volk/gen/make_set_simd.py deleted file mode 100644 index 8334487d7..000000000 --- a/volk/gen/make_set_simd.py +++ /dev/null @@ -1,166 +0,0 @@ -# -# Copyright 2010 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/>. -# - -from xml.dom import minidom - -def make_set_simd(dom, machines) : - tempstring = ""; - tempstring = tempstring +'dnl this file is auto generated by volk_register.py\n\n'; - - tempstring = tempstring +'\ndnl define arch checks\n'; - for domarch in dom: - if str(domarch.attributes["type"].value) != "all": - arch = str(domarch.attributes["name"].value); - flag = domarch.getElementsByTagName("flag"); - flag = str(flag[0].firstChild.data); - tempstring = tempstring + "AC_DEFUN([_TRY_ADD_" + arch.swapcase() + "],\n"; - tempstring = tempstring + "[\n"; - tempstring = tempstring + " LF_CHECK_CC_FLAG([-" + flag + "])\n"; - tempstring = tempstring + " LF_CHECK_CXX_FLAG([-" + flag + "])\n"; - tempstring = tempstring + "])\n"; - - tempstring = tempstring +'\ndnl main set_simd_flags\n'; - tempstring = tempstring + "AC_DEFUN([LV_SET_SIMD_FLAGS],\n"; - tempstring = tempstring + "[\n"; - #tempstring = tempstring + " AC_REQUIRE([GR_SET_MD_CPU])\n"; - tempstring = tempstring + " AC_SUBST(LV_CXXFLAGS)\n"; - tempstring = tempstring + " indCC=no\n"; - tempstring = tempstring + " indCXX=no\n"; - tempstring = tempstring + " indLV_ARCH=no\n"; - tempstring = tempstring + " AC_ARG_WITH(lv_arch,\n"; - tempstring = tempstring + " AC_HELP_STRING([--with-lv_arch=ARCH],[set volk hardware speedups as space separated string with elements from the following list("; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + arch + ", " - tempstring = tempstring[0:len(tempstring) - 2]; - - tempstring = tempstring + ")]),\n"; - tempstring = tempstring + " [cf_with_lv_arch=\"$withval\"],\n"; - tempstring = tempstring + " [cf_with_lv_arch=\"\"])\n"; - if str(domarch.attributes["type"].value) == "all": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " AC_DEFINE(LV_MAKE_" + arch.swapcase() + ", 1, [always set "+ arch + "!])\n"; - tempstring = tempstring + " ADDONS=\"\"\n"; - tempstring = tempstring + " BUILT_ARCHS=\"\"\n"; - #tempstring = tempstring + " _MAKE_FAKE_PROCCPU\n"; - tempstring = tempstring + " OVERRULE_FLAG=\"no\"\n"; - tempstring = tempstring + " if test -z \"$cf_with_lv_arch\"; then\n"; - tempstring = tempstring + " cf_with_lv_arch=\""; - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + arch + " "; - tempstring = tempstring[0:-1] + "\"\n"; - tempstring = tempstring + " OVERRULE_FLAG=\"yes\"\n"; - tempstring = tempstring + " fi\n"; - - tempstring = tempstring +'\ndnl init LV_MAKE_XXX and then try to add archs\n'; - for domarch in dom: - if str(domarch.attributes["type"].value) != "all": - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " LV_MAKE_" + arch.swapcase() + "=no\n"; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - atype = str(domarch.attributes["type"].value); - if atype != "all": - tempstring = tempstring + " _TRY_ADD_" + arch.swapcase() + "\n"; - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - atype = str(domarch.attributes["type"].value); - tempstring = tempstring +'\ndnl add in flags for arch ' + arch + '\n'; - overrule = domarch.getElementsByTagName("overrule"); - if overrule: - overrule = str(overrule[0].firstChild.data); - else: - overrule = ""; - overrule_val = domarch.getElementsByTagName("overrule_val"); - if overrule_val: - overrule_val = str(overrule_val[0].firstChild.data); - else: - overrule_val = ""; - flag = domarch.getElementsByTagName("flag"); - flag = str(flag[0].firstChild.data); - if atype != "all": - tempstring = tempstring + " for i in $lf_CXXFLAGS\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X-" + flag +"; then\n"; - tempstring = tempstring + " indCXX=yes\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " for i in $lf_CFLAGS\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X-" + flag +"; then\n"; - tempstring = tempstring + " indCC=yes\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " for i in $cf_with_lv_arch\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X" + arch + "; then\n"; - tempstring = tempstring + " indLV_ARCH=yes\n" - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " if test -n \"" + overrule + "\" && test \"$" + overrule + "\" == \"" + overrule_val + "\" && test \"$OVERRULE_FLAG\" == \"yes\" && test \"$indLV_ARCH\" == \"yes\"; then\n" - tempstring = tempstring + " indLV_ARCH=no\n" - tempstring = tempstring + " fi\n" - - tempstring = tempstring + " if test \"$indCC\" == \"yes\" && test \"$indCXX\" == \"yes\" && test \"$indLV_ARCH\" == \"yes\"; then\n" - - #tempstring = tempstring + " ADDONS=\"${ADDONS} -" + flag + "\"\n"; - tempstring = tempstring + " BUILT_ARCHS=\"${BUILT_ARCHS} " + arch + "\"\n"; - tempstring = tempstring + " LV_MAKE_" + arch.swapcase() + "=yes\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " indCC=no\n" - tempstring = tempstring + " indCXX=no\n" - tempstring = tempstring + " indLV_ARCH=no\n" - else: - tempstring = tempstring + " for i in $cf_with_lv_arch\n" - tempstring = tempstring + " do\n" - tempstring = tempstring + " if test \"X$i\" = X" + arch + "; then\n"; - tempstring = tempstring + " indLV_ARCH=yes\n" - tempstring = tempstring + " fi\n" - tempstring = tempstring + " done\n" - tempstring = tempstring + " if test -n \"" + overrule + "\" && test \"$" + overrule + "\" == \"" + overrule_val + "\" && test \"$OVERRULE_FLAG\" == \"yes\" && test \"$indLV_ARCH\" == \"yes\"; then\n" - tempstring = tempstring + " indLV_ARCH=no\n" - tempstring = tempstring + " fi\n" - tempstring = tempstring + " if test \"$indLV_ARCH\" == \"yes\"; then\n" - tempstring = tempstring + " LV_MAKE_" + arch.swapcase() + "=yes\n"; - tempstring = tempstring + " BUILT_ARCHS=\"${BUILT_ARCHS} " + arch + "\"\n"; - tempstring = tempstring + " fi\n" - tempstring = tempstring + " indLV_ARCH=no\n" - - - for domarch in dom: - arch = str(domarch.attributes["name"].value); - tempstring = tempstring + " AM_CONDITIONAL(LV_MAKE_" + arch.swapcase() + ", test \"$LV_MAKE_" + arch.swapcase() + "\" == \"yes\")\n"; - - tempstring += "\n" - #now we can define the machines we're compiling - for machine_name in machines: - tempstring += " AM_CONDITIONAL(LV_MACHINE_" + machine_name.swapcase() + ", " - marchlist = machines[machine_name] - for march in marchlist: - tempstring += "test \"$LV_MAKE_" + march.swapcase() + "\" == \"yes\" && " - - tempstring += "test true)\n" #just so we don't have to detect the last one in the group, i know - tempstring = tempstring + " LV_CXXFLAGS=\"${LV_CXXFLAGS} ${ADDONS}\"\n" - tempstring = tempstring + "])\n" - - return tempstring; - - diff --git a/volk/gen/make_typedefs.py b/volk/gen/make_typedefs.py deleted file mode 100644 index 09221d2ef..000000000 --- a/volk/gen/make_typedefs.py +++ /dev/null @@ -1,23 +0,0 @@ -from xml.dom import minidom -import string -from volk_regexp import * - - - -def make_typedefs(funclist, retlist, my_argtypelist) : - tempstring = ""; - tempstring = tempstring + '/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '/*this file is auto generated by volk_register.py*/'; - tempstring = tempstring + '\n#ifndef INCLUDED_VOLK_TYPEDEFS'; - tempstring = tempstring + '\n#define INCLUDED_VOLK_TYPEDEFS\n'; - tempstring = tempstring + '\n\n#include<inttypes.h>\n'; - tempstring = tempstring + '#include<volk/volk_complex.h>\n'; - - tempstring = tempstring + '\n'; - - for i in range(len(funclist)): - tempstring = tempstring + "typedef " + retlist[i] +" (*" + replace_volk.sub("p", funclist[i]) + ")(" + my_argtypelist[i] + ");\n"; - - tempstring = tempstring + "#endif /*INCLUDED_VOLK_TYPEDEFS*/\n"; - - return tempstring; diff --git a/volk/gen/volk_arch_defs.py b/volk/gen/volk_arch_defs.py new file mode 100644 index 000000000..41154d5a7 --- /dev/null +++ b/volk/gen/volk_arch_defs.py @@ -0,0 +1,92 @@ +# +# Copyright 2012 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/>. +# + +archs = list() +arch_dict = dict() + +#TODO enable this when we are ready +create_unaligned_archs = False + +class arch_class: + def __init__(self, flags, checks, **kwargs): + for key, cast, failval in ( + ('name', str, None), + ('environment', str, None), + ('include', str, None), + ('alignment', int, 1) + ): + try: setattr(self, key, cast(kwargs[key])) + except: setattr(self, key, failval) + self.checks = checks + assert(self.name) + self._flags = flags + + def is_supported(self, compiler): + if not self._flags.keys(): return True + return compiler in self._flags.keys() + + def get_flags(self, compiler): + try: return self._flags[compiler] + except KeyError: return list() + + def __repr__(self): return self.name + +def register_arch(**kwargs): + arch = arch_class(**kwargs) + archs.append(arch) + arch_dict[arch.name] = arch + if arch.alignment > 1 and create_unaligned_archs: + kwargs['name'] += '_u' + kwargs['alignment'] = 1 + register_arch(**kwargs) + +######################################################################## +# register the arches +######################################################################## +#TODO skip the XML and put it here +from xml.dom import minidom +import os +gendir = os.path.dirname(__file__) +archs_xml = minidom.parse(os.path.join(gendir, 'archs.xml')).getElementsByTagName('arch') +for arch_xml in archs_xml: + kwargs = dict() + for attr in arch_xml.attributes.keys(): + kwargs[attr] = arch_xml.attributes[attr].value + for node in arch_xml.childNodes: + try: + name = node.tagName + val = arch_xml.getElementsByTagName(name)[0].firstChild.data + kwargs[name] = val + except: pass + checks = list() + for check_xml in arch_xml.getElementsByTagName("check"): + name = check_xml.attributes["name"].value + params = list() + for param_xml in check_xml.getElementsByTagName("param"): + params.append(param_xml.firstChild.data) + checks.append([name, params]) + flags = dict() + for flag_xml in arch_xml.getElementsByTagName("flag"): + name = flag_xml.attributes["compiler"].value + if not flags.has_key(name): flags[name] = list() + flags[name].append(flag_xml.firstChild.data) + #force kwargs keys to be of type str, not unicode for py25 + kwargs = dict((str(k), v) for k, v in kwargs.iteritems()) + register_arch(flags=flags, checks=checks, **kwargs) + +if __name__ == '__main__': + print archs diff --git a/volk/gen/volk_compile_utils.py b/volk/gen/volk_compile_utils.py new file mode 100644 index 000000000..cf1357375 --- /dev/null +++ b/volk/gen/volk_compile_utils.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2012 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/>. +# + +import optparse +import volk_arch_defs +import volk_machine_defs + +def do_arch_flags_list(compiler): + output = list() + for arch in volk_arch_defs.archs: + if not arch.is_supported(compiler): continue + fields = [arch.name] + arch.get_flags(compiler) + output.append(','.join(fields)) + print ';'.join(output) + +def do_machines_list(arch_names): + output = list() + for machine in volk_machine_defs.machines: + machine_arch_set = set(machine.arch_names) + if set(arch_names).intersection(machine_arch_set) == machine_arch_set: + output.append(machine.name) + print ';'.join(output) + +def do_machine_flags_list(compiler, machine_name): + output = list() + machine = volk_machine_defs.machine_dict[machine_name] + for arch in machine.archs: + output.extend(arch.get_flags(compiler)) + print ' '.join(output) + +def main(): + parser = optparse.OptionParser() + parser.add_option('--mode', type='string') + parser.add_option('--compiler', type='string') + parser.add_option('--archs', type='string') + parser.add_option('--machine', type='string') + (opts, args) = parser.parse_args() + + if opts.mode == 'arch_flags': return do_arch_flags_list(opts.compiler.lower()) + if opts.mode == 'machines': return do_machines_list(opts.archs.split(';')) + if opts.mode == 'machine_flags': return do_machine_flags_list(opts.compiler.lower(), opts.machine) + +if __name__ == '__main__': main() diff --git a/volk/gen/volk_kernel_defs.py b/volk/gen/volk_kernel_defs.py new file mode 100644 index 000000000..52cdb684c --- /dev/null +++ b/volk/gen/volk_kernel_defs.py @@ -0,0 +1,224 @@ +# +# 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. +# + +import os +import re +import sys +import glob + +from volk_arch_defs import archs + +remove_after_underscore = re.compile("_.*"); +space_remove = re.compile(" "); +leading_space_remove = re.compile("^ *"); +replace_arch = re.compile(", const char\* arch"); +replace_bracket = re.compile(" {"); +replace_volk = re.compile("volk"); + +def strip_trailing(tostrip, stripstr): + lindex = tostrip.rfind(stripstr) + tostrip = tostrip[0:lindex] + tostrip[lindex:len(tostrip)].replace(stripstr, ""); + return tostrip + +srcdir = os.path.dirname(os.path.dirname(__file__)) +hdr_files = glob.glob(os.path.join(srcdir, "include/volk/*.h")) + +datatypes = []; +functions = []; + +for line in hdr_files: + subline = re.search(".*_(a|u)\.h.*", os.path.basename(line)) + if subline: + subsubline = re.search("(?<=volk_).*", subline.group(0)); + if subsubline: + dtype = remove_after_underscore.sub("", subsubline.group(0)); + subdtype = re.search("[0-9]+[A-z]+", dtype); + if subdtype: + datatypes.append(subdtype.group(0)); + + +datatypes = set(datatypes); + +for line in hdr_files: + for dt in datatypes: + if dt in line: + subline = re.search("(volk_" + dt +"_.*(a|u).*\.h)", line); + if subline: + + subsubline = re.search(".+(?=\.h)", subline.group(0)); + functions.append(subsubline.group(0)); + +archs_or = "(" +for arch in archs: + archs_or = archs_or + arch.name.upper() + "|"; +archs_or = archs_or[0:len(archs_or)-1]; +archs_or = archs_or + ")"; + +taglist = []; +fcountlist = []; +arched_arglist = []; +retlist = []; +my_arglist = []; +my_argtypelist = []; +for func in functions: + tags = []; + fcount = []; + infile_source = open(os.path.join(srcdir, 'include', 'volk', func + ".h")) + begun_name = 0; + begun_paren = 0; + sourcefile = infile_source.readlines(); + infile_source.close(); + for line in sourcefile: +#FIXME: make it work for multiple #if define()s + archline = re.search("^\#if.*?LV_HAVE_" + archs_or + ".*", line); + if archline: + arch = archline.group(0); + archline = re.findall(archs_or + "(?=( |\n|&))", line); + if archline: + archsublist = []; + for tup in archline: + archsublist.append(tup[0]); + fcount.append(archsublist); + testline = re.search("static inline.*?" + func, line); + if (not testline): + continue + tagline = re.search(func + "_.+", line); + if tagline: + tag = re.search("(?<=" + func + "_)\w+(?= *\()",line); + if tag: + tag = re.search("\w+", tag.group(0)); + if tag: + tags.append(tag.group(0)); + + + if begun_name == 0: + retline = re.search(".+(?=" + func + ")", line); + if retline: + ret = retline.group(0); + + + + + subline = re.search(func + ".*", line); + if subline: + subsubline = re.search("\(.*?\)", subline.group(0)); + if subsubline: + args = subsubline.group(0); + + else: + begun_name = 1; + subsubline = re.search("\(.*", subline.group(0)); + if subsubline: + args = subsubline.group(0); + begun_paren = 1; + else: + if begun_paren == 1: + subline = re.search(".*?\)", line); + if subline: + args = args + subline.group(0); + begun_name = 0; + begun_paren = 0; + else: + subline = re.search(".*", line); + args = args + subline.group(0); + else: + subline = re.search("\(.*?\)", line); + if subline: + args = subline.group(0); + begun_name = 0; + else: + subline = re.search("\(.*", line); + if subline: + args = subline.group(0); + begun_paren = 1; + + replace = re.compile("static "); + ret = replace.sub("", ret); + replace = re.compile("inline "); + ret = replace.sub("", ret); + arched_args = args[args.find('(')+1:args.find(')')] + + remove = re.compile('\)|\(|{'); + rargs = remove.sub("", args); + sargs = rargs.split(','); + + + + margs = []; + atypes = []; + for arg in sargs: + temp = arg.split(" "); + margs.append(temp[-1]); + replace = re.compile(" " + temp[-1]); + atypes.append(replace.sub("", arg)); + + + my_args = "" + arg_types = "" + for arg in range(0, len(margs) - 1): + this_arg = leading_space_remove.sub("", margs[arg]); + my_args = my_args + this_arg + ", "; + this_type = leading_space_remove.sub("", atypes[arg]); + arg_types = arg_types + this_type + ", "; + + this_arg = leading_space_remove.sub("", margs[-1]); + my_args = my_args + this_arg; + this_type = leading_space_remove.sub("", atypes[-1]); + arg_types = arg_types + this_type; + my_argtypelist.append(arg_types); + + if(ret[-1] != ' '): + ret = ret + ' '; + + arched_arglist.append(arched_args); #!!!!!!!!!!! + my_arglist.append(my_args) #!!!!!!!!!!!!!!!!! + retlist.append(ret); + fcountlist.append(fcount); + taglist.append(tags); + +class kernel_class: + def __init__(self, index): + self.name = functions[index] + self.pname = self.name.replace('volk_', 'p_') + self.rettype = retlist[index] + self.arglist_defs = my_argtypelist[index] + self.arglist_namedefs = arched_arglist[index] + self.arglist_names = my_arglist[index] + self._tagdeps = fcountlist[index] + self._taglist = taglist[index] + + def get_tags(self, archs): + def is_in(x): return x.lower() in archs + taglist = list() + tagdeps = list() + for i in range(len(self._tagdeps)): + if all(map(is_in, self._tagdeps[i])): + taglist.append(self._taglist[i]) + tagdeps.append(self._tagdeps[i]) + return taglist, tagdeps + + def __repr__(self): + return self.name + +kernels = map(kernel_class, range(len(retlist))) + +if __name__ == '__main__': + print kernels diff --git a/volk/gen/volk_machine_defs.py b/volk/gen/volk_machine_defs.py new file mode 100644 index 000000000..d1a856981 --- /dev/null +++ b/volk/gen/volk_machine_defs.py @@ -0,0 +1,78 @@ +# +# Copyright 2012 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/>. +# + +from volk_arch_defs import arch_dict + +machines = list() +machine_dict = dict() + +class machine_class: + def __init__(self, name, archs): + self.name = name + self.archs = list() + self.arch_names = list() + for arch_name in archs: + if not arch_name: continue + arch = arch_dict[arch_name] + self.archs.append(arch) + self.arch_names.append(arch_name) + arch_name += '_u' + if arch.alignment > 1 and arch_dict.has_key(arch_name): + arch = arch_dict[arch_name] + self.archs.append(arch) + self.alignment = max(map(lambda a: a.alignment, self.archs)) + + def __repr__(self): return self.name + +def register_machine(name, archs): + for i, arch_name in enumerate(archs): + if '|' in arch_name: #handle special arch names with the '|' + for arch_sub in arch_name.split('|'): + if arch_sub: + register_machine(name+'_'+arch_sub, archs[:i] + [arch_sub] + archs[i+1:]) + else: + register_machine(name, archs[:i] + archs[i+1:]) + return + machine = machine_class(name=name, archs=archs) + machines.append(machine) + machine_dict[machine.name] = machine + +######################################################################## +# register the machines +######################################################################## +#TODO skip the XML and put it here +from xml.dom import minidom +import os +gendir = os.path.dirname(__file__) +machines_xml = minidom.parse(os.path.join(gendir, 'machines.xml')).getElementsByTagName('machine') +for machine_xml in machines_xml: + kwargs = dict() + for attr in machine_xml.attributes.keys(): + kwargs[attr] = machine_xml.attributes[attr].value + for node in machine_xml.childNodes: + try: + name = node.tagName + val = machine_xml.getElementsByTagName(name)[0].firstChild.data + kwargs[name] = val + except: pass + kwargs['archs'] = kwargs['archs'].split() + #force kwargs keys to be of type str, not unicode for py25 + kwargs = dict((str(k), v) for k, v in kwargs.iteritems()) + register_machine(**kwargs) + +if __name__ == '__main__': + print machines diff --git a/volk/gen/volk_regexp.py b/volk/gen/volk_regexp.py deleted file mode 100644 index eb4ceb54b..000000000 --- a/volk/gen/volk_regexp.py +++ /dev/null @@ -1,13 +0,0 @@ -import re - -remove_after_underscore = re.compile("_.*"); -space_remove = re.compile(" "); -leading_space_remove = re.compile("^ *"); -replace_arch = re.compile(", const char\* arch"); -replace_bracket = re.compile(" {"); -replace_volk = re.compile("volk"); - -def strip_trailing(tostrip, stripstr): - lindex = tostrip.rfind(stripstr) - tostrip = tostrip[0:lindex] + tostrip[lindex:len(tostrip)].replace(stripstr, ""); - return tostrip diff --git a/volk/gen/volk_register.py b/volk/gen/volk_register.py deleted file mode 100644 index 3a237c5ca..000000000 --- a/volk/gen/volk_register.py +++ /dev/null @@ -1,303 +0,0 @@ -#! /usr/bin/env python - -import sys -import os -import re -import glob -from xml.dom import minidom -from volk_regexp import * -from make_cpuid_c import make_cpuid_c -from make_cpuid_h import make_cpuid_h -from make_set_simd import make_set_simd -from make_config_fixed import make_config_fixed -from make_typedefs import make_typedefs -from make_environment_init_c import make_environment_init_c -from make_environment_init_h import make_environment_init_h -from make_makefile_am import make_makefile_am -from make_machines_h import make_machines_h -from make_machines_c import make_machines_c -from make_each_machine_c import make_each_machine_c -from make_c import make_c -from make_h import make_h -import copy - -#set srcdir and gendir -srcdir = os.path.dirname(os.path.dirname(__file__)) -try: gendir = sys.argv[1] -except: gendir = os.path.dirname(__file__) - -#ensure directories exist -for dir in ( - (os.path.join(gendir, 'include', 'volk')), - (os.path.join(gendir, 'lib')), - (os.path.join(gendir, 'config')) -): - if not os.path.exists(dir): os.makedirs(dir) - -outfile_set_simd = open(os.path.join(gendir, "config/lv_set_simd_flags.m4"), "w") -outfile_h = open(os.path.join(gendir, "include/volk/volk.h"), "w") -outfile_c = open(os.path.join(gendir, "lib/volk.c"), "w") -outfile_typedefs = open(os.path.join(gendir, "include/volk/volk_typedefs.h"), "w") -outfile_init_h = open(os.path.join(gendir, "lib/volk_init.h"), "w") -outfile_cpu_h = open(os.path.join(gendir, "include/volk/volk_cpu.h"), "w") -outfile_cpu_c = open(os.path.join(gendir, "lib/volk_cpu.c"), "w") -#outfile_config_in = open(os.path.join(gendir, "include/volk/volk_config.h.in"), "w") -outfile_config_fixed = open(os.path.join(gendir, "include/volk/volk_config_fixed.h"), "w") -outfile_environment_c = open(os.path.join(gendir, "lib/volk_environment_init.c"), "w") -outfile_environment_h = open(os.path.join(gendir, "lib/volk_environment_init.h"), "w") -outfile_makefile_am = open(os.path.join(gendir, "lib/Makefile.am"), "w") -outfile_machines_h = open(os.path.join(gendir, "lib/volk_machines.h"), "w") -outfile_machines_c = open(os.path.join(gendir, "lib/volk_machines.c"), "w") -hdr_files = glob.glob(os.path.join(srcdir, "include/volk/*.h")) - -datatypes = []; -functions = []; - -for line in hdr_files: - subline = re.search(".*_(a|u)\.h.*", os.path.basename(line)) - if subline: - subsubline = re.search("(?<=volk_).*", subline.group(0)); - if subsubline: - dtype = remove_after_underscore.sub("", subsubline.group(0)); - subdtype = re.search("[0-9]+[A-z]+", dtype); - if subdtype: - datatypes.append(subdtype.group(0)); - - -datatypes = set(datatypes); - -for line in hdr_files: - for dt in datatypes: - if dt in line: - subline = re.search("(volk_" + dt +"_.*(a|u).*\.h)", line); - if subline: - - subsubline = re.search(".+(?=\.h)", subline.group(0)); - functions.append(subsubline.group(0)); - -archs = []; -afile = minidom.parse(os.path.join(srcdir, "gen/archs.xml")) -filearchs = afile.getElementsByTagName("arch"); -for filearch in filearchs: - archs.append(str(filearch.attributes["name"].value)); - -for arch in archs: - a_var = re.search("^\$", arch); - if a_var: - archs.remove(arch); - -#strip out mutex archs - -archflags_dict = {} -for filearch in filearchs: - archflags_dict[str(filearch.attributes["name"].value)] = str(filearch.getElementsByTagName("flag")[0].firstChild.data) - -archalign_dict = {} -for filearch in filearchs: - alignelem = filearch.getElementsByTagName("alignment") - if(alignelem): - archalign_dict[str(filearch.attributes["name"].value)] = int(alignelem[0].firstChild.data) - -archs_or = "(" -for arch in archs: - archs_or = archs_or + arch.upper() + "|"; -archs_or = archs_or[0:len(archs_or)-1]; -archs_or = archs_or + ")"; - -#get machine list and parse to a list of machines, each with a list of archs (none of this DOM crap) -machine_str_dict = {} -mfile = minidom.parse(os.path.join(srcdir, "gen/machines.xml")) -filemachines = mfile.getElementsByTagName("machine") - -for filemachine in filemachines: - machine_str_dict[str(filemachine.attributes["name"].value)] = str(filemachine.getElementsByTagName("archs")[0].firstChild.data).split() - -#all right now you have a dict of arch lists -#next we expand it -#this is an expanded list accounting for the OR syntax -#TODO: make this work for multiple "|" machines -machines = {} -already_done = False -for machine_name in machine_str_dict: - already_done = False - marchlist = machine_str_dict[machine_name] - for march in marchlist: - or_marchs = march.split("|") - if len(or_marchs) > 1: - marchlist.remove(march) - for or_march in or_marchs: - tempmarchlist = copy.deepcopy(marchlist) - tempmarchlist.append(or_march) - machines[machine_name + "_" + or_march] = tempmarchlist - already_done = True - - if not already_done: - machines[machine_name] = marchlist - -#get the maximum alignment for all archs in a machine -machine_alignment_dict = {} -for machine in machines: - machine_alignment_dict[machine] = max((archalign_dict.get(k, 1)) for k in machines[machine]) - -#for machine in machine_alignment_dict: -# print machine + ": %d" % machine_alignment_dict[machine] - -taglist = []; -fcountlist = []; -arched_arglist = []; -retlist = []; -my_arglist = []; -my_argtypelist = []; -for func in functions: - tags = []; - fcount = []; - infile_source = open(os.path.join(srcdir, 'include', 'volk', func + ".h")) - begun_name = 0; - begun_paren = 0; - sourcefile = infile_source.readlines(); - infile_source.close(); - for line in sourcefile: -#FIXME: make it work for multiple #if define()s - archline = re.search("^\#if.*?LV_HAVE_" + archs_or + ".*", line); - if archline: - arch = archline.group(0); - archline = re.findall(archs_or + "(?=( |\n|&))", line); - if archline: - archsublist = []; - for tup in archline: - archsublist.append(tup[0]); - fcount.append(archsublist); - testline = re.search("static inline.*?" + func, line); - if (not testline): - continue - tagline = re.search(func + "_.+", line); - if tagline: - tag = re.search("(?<=" + func + "_)\w+(?= *\()",line); - if tag: - tag = re.search("\w+", tag.group(0)); - if tag: - tags.append(tag.group(0)); - - - if begun_name == 0: - retline = re.search(".+(?=" + func + ")", line); - if retline: - ret = retline.group(0); - - - - - subline = re.search(func + ".*", line); - if subline: - subsubline = re.search("\(.*?\)", subline.group(0)); - if subsubline: - args = subsubline.group(0); - - else: - begun_name = 1; - subsubline = re.search("\(.*", subline.group(0)); - if subsubline: - args = subsubline.group(0); - begun_paren = 1; - else: - if begun_paren == 1: - subline = re.search(".*?\)", line); - if subline: - args = args + subline.group(0); - begun_name = 0; - begun_paren = 0; - else: - subline = re.search(".*", line); - args = args + subline.group(0); - else: - subline = re.search("\(.*?\)", line); - if subline: - args = subline.group(0); - begun_name = 0; - else: - subline = re.search("\(.*", line); - if subline: - args = subline.group(0); - begun_paren = 1; - - replace = re.compile("static "); - ret = replace.sub("", ret); - replace = re.compile("inline "); - ret = replace.sub("", ret); - replace = re.compile("\)"); - arched_args = replace.sub(", const char* arch) {", args); - - remove = re.compile('\)|\(|{'); - rargs = remove.sub("", args); - sargs = rargs.split(','); - - - - margs = []; - atypes = []; - for arg in sargs: - temp = arg.split(" "); - margs.append(temp[-1]); - replace = re.compile(" " + temp[-1]); - atypes.append(replace.sub("", arg)); - - - my_args = "" - arg_types = "" - for arg in range(0, len(margs) - 1): - this_arg = leading_space_remove.sub("", margs[arg]); - my_args = my_args + this_arg + ", "; - this_type = leading_space_remove.sub("", atypes[arg]); - arg_types = arg_types + this_type + ", "; - - this_arg = leading_space_remove.sub("", margs[-1]); - my_args = my_args + this_arg; - this_type = leading_space_remove.sub("", atypes[-1]); - arg_types = arg_types + this_type; - my_argtypelist.append(arg_types); - - if(ret[-1] != ' '): - ret = ret + ' '; - - arched_arglist.append(arched_args); #!!!!!!!!!!! - my_arglist.append(my_args) #!!!!!!!!!!!!!!!!! - retlist.append(ret); - fcountlist.append(fcount); - taglist.append(tags); - - -outfile_cpu_h.write(make_cpuid_h(filearchs)); -outfile_cpu_h.close(); - -outfile_cpu_c.write(make_cpuid_c(filearchs)); -outfile_cpu_c.close(); - -outfile_set_simd.write(make_set_simd(filearchs, machines)); -outfile_set_simd.close(); - -outfile_config_fixed.write(make_config_fixed(filearchs)); -outfile_config_fixed.close(); - -outfile_typedefs.write(make_typedefs(functions, retlist, my_argtypelist)); -outfile_typedefs.close(); - -outfile_makefile_am.write(make_makefile_am(filearchs, machines, archflags_dict)) -outfile_makefile_am.close() - -outfile_machines_h.write(make_machines_h(functions, machines, archs)) -outfile_machines_h.close() - -outfile_machines_c.write(make_machines_c(machines)) -outfile_machines_c.close() - -outfile_c.write(make_c(machines, archs, functions, arched_arglist, my_arglist)) -outfile_c.close() - -outfile_h.write(make_h(functions, arched_arglist)) -outfile_h.close() - -for machine in machines: - machine_c_filename = os.path.join(gendir, "lib/volk_machine_" + machine + ".c") - outfile_machine_c = open(machine_c_filename, "w") - outfile_machine_c.write(make_each_machine_c(machine, machines[machine], functions, fcountlist, taglist, machine_alignment_dict[machine])) - outfile_machine_c.close() diff --git a/volk/gen/volk_tmpl_utils.py b/volk/gen/volk_tmpl_utils.py new file mode 100644 index 000000000..6c08a8213 --- /dev/null +++ b/volk/gen/volk_tmpl_utils.py @@ -0,0 +1,74 @@ +#!/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. +# + +import os +import re +import sys +import optparse +import volk_arch_defs +import volk_machine_defs +import volk_kernel_defs +from Cheetah import Template + +def __escape_pre_processor(code): + out = list() + for line in code.splitlines(): + m = re.match('^(\s*)#(\s*)(\w+)(.*)$', line) + if m: + p0, p1, fcn, stuff = m.groups() + conly = fcn in ('include', 'define', 'ifdef', 'ifndef', 'endif', 'elif', 'pragma') + both = fcn in ('if', 'else') + istmpl = '$' in stuff + if 'defined' in stuff: istmpl = False + if conly or (both and not istmpl): + line = '%s\\#%s%s%s'%(p0, p1, fcn, stuff) + out.append(line) + return '\n'.join(out) + +def __parse_tmpl(_tmpl, **kwargs): + defs = { + 'archs': volk_arch_defs.archs, + 'arch_dict': volk_arch_defs.arch_dict, + 'machines': volk_machine_defs.machines, + 'machine_dict': volk_machine_defs.machine_dict, + 'kernels': volk_kernel_defs.kernels, + } + defs.update(kwargs) + _tmpl = __escape_pre_processor(_tmpl) + _tmpl = """ + +/* this file was generated by volk template utils, do not edit! */ + +""" + _tmpl + return str(Template.Template(_tmpl, defs)) + +def main(): + parser = optparse.OptionParser() + parser.add_option('--input', type='string') + parser.add_option('--output', type='string') + (opts, args) = parser.parse_args() + + output = __parse_tmpl(open(opts.input).read(), args=args) + if opts.output: open(opts.output, 'w').write(output) + else: print output + +if __name__ == '__main__': main() diff --git a/volk/include/volk/volk_32fc_s32fc_rotatorpuppet_32fc_a.h b/volk/include/volk/volk_32fc_s32fc_rotatorpuppet_32fc_a.h new file mode 100644 index 000000000..eee9f0064 --- /dev/null +++ b/volk/include/volk/volk_32fc_s32fc_rotatorpuppet_32fc_a.h @@ -0,0 +1,74 @@ +#ifndef INCLUDED_volk_32fc_s32fc_rotatorpuppet_32fc_a_H +#define INCLUDED_volk_32fc_s32fc_rotatorpuppet_32fc_a_H + + +#include <volk/volk_complex.h> +#include <stdio.h> +#include <volk/volk_32fc_s32fc_x2_rotator_32fc_a.h> + + +#ifdef LV_HAVE_GENERIC + +/*! + \brief rotate input vector at fixed rate per sample from initial phase offset + \param outVector The vector where the results will be stored + \param inVector Vector to be rotated + \param phase_inc rotational velocity + \param phase initial phase offset + \param num_points The number of values in inVector to be rotated and stored into cVector +*/ + + +static inline void volk_32fc_s32fc_rotatorpuppet_32fc_a_generic(lv_32fc_t* outVector, const lv_32fc_t* inVector, const lv_32fc_t phase_inc, unsigned int num_points){ + lv_32fc_t phase[1] = {lv_cmake(.3, 0.95393)}; + volk_32fc_s32fc_x2_rotator_32fc_a_generic(outVector, inVector, phase_inc, phase, num_points); + +} +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> + +static inline void volk_32fc_s32fc_rotatorpuppet_32fc_a_sse4_1(lv_32fc_t* outVector, const lv_32fc_t* inVector, const lv_32fc_t phase_inc, unsigned int num_points){ + lv_32fc_t phase[1] = {lv_cmake(.3, .95393)}; + volk_32fc_s32fc_x2_rotator_32fc_a_sse4_1(outVector, inVector, phase_inc, phase, num_points); + +} + + + + +#endif /* LV_HAVE_SSE4_1 */ + +#ifdef LV_HAVE_AVX +#include <immintrin.h> + +/*! + \brief rotate input vector at fixed rate per sample from initial phase offset + \param outVector The vector where the results will be stored + \param inVector Vector to be rotated + \param phase_inc rotational velocity + \param phase initial phase offset + \param num_points The number of values in inVector to be rotated and stored into cVector +*/ + + + + +static inline void volk_32fc_s32fc_rotatorpuppet_32fc_a_avx(lv_32fc_t* outVector, const lv_32fc_t* inVector, const lv_32fc_t phase_inc, unsigned int num_points){ + lv_32fc_t phase[1] = {lv_cmake(.3, .95393)}; + volk_32fc_s32fc_x2_rotator_32fc_a_avx(outVector, inVector, phase_inc, phase, num_points); + +} + +#endif /* LV_HAVE_AVX */ + + + + + + + + +#endif /* INCLUDED_volk_32fc_s32fc_rotatorpuppet_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 new file mode 100644 index 000000000..80c55e75f --- /dev/null +++ b/volk/include/volk/volk_32fc_s32fc_x2_rotator_32fc_a.h @@ -0,0 +1,262 @@ +#ifndef INCLUDED_volk_32fc_s32fc_rotator_32fc_a_H +#define INCLUDED_volk_32fc_s32fc_rotator_32fc_a_H + + +#include <volk/volk_complex.h> +#include <stdio.h> +#include <stdlib.h> +#define ROTATOR_RELOAD 512 + + +#ifdef LV_HAVE_GENERIC + +/*! + \brief rotate input vector at fixed rate per sample from initial phase offset + \param outVector The vector where the results will be stored + \param inVector Vector to be rotated + \param phase_inc rotational velocity + \param phase initial phase offset + \param num_points The number of values in inVector to be rotated and stored into cVector +*/ + + +static inline void volk_32fc_s32fc_x2_rotator_32fc_a_generic(lv_32fc_t* outVector, const lv_32fc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points){ + *phase = lv_cmake(1.0, 0.0); + unsigned int i = 0; + int j = 0; + for(i = 0; i < (unsigned int)(num_points/ROTATOR_RELOAD); ++i) { + for(j = 0; j < ROTATOR_RELOAD; ++j) { + *outVector++ = *inVector++ * (*phase); + (*phase) *= phase_inc; + } + (*phase) /= abs((*phase)); + } + for(i = 0; i < num_points%ROTATOR_RELOAD; ++i) { + *outVector++ = *inVector++ * (*phase); + (*phase) *= phase_inc; + } + +} +#endif /* LV_HAVE_GENERIC */ + + +#ifdef LV_HAVE_SSE4_1 +#include <smmintrin.h> + +static inline void volk_32fc_s32fc_x2_rotator_32fc_a_sse4_1(lv_32fc_t* outVector, const lv_32fc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points){ + *phase = lv_cmake(1.0, 0.0); + lv_32fc_t* cPtr = outVector; + const lv_32fc_t* aPtr = inVector; + lv_32fc_t incr = 1; + lv_32fc_t phase_Ptr[2] = {(*phase), (*phase)}; + + unsigned int i, j = 0; + + for(i = 0; i < 2; ++i) { + phase_Ptr[i] *= incr; + incr *= (phase_inc); + } + + /*printf("%f, %f\n", lv_creal(phase_Ptr[0]), lv_cimag(phase_Ptr[0])); + printf("%f, %f\n", lv_creal(phase_Ptr[1]), lv_cimag(phase_Ptr[1])); + 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));*/ + __m128 aVal, phase_Val, inc_Val, yl, yh, tmp1, tmp2, z, ylp, yhp, tmp1p, tmp2p; + + phase_Val = _mm_loadu_ps((float*)phase_Ptr); + inc_Val = _mm_set_ps(lv_cimag(incr), lv_creal(incr),lv_cimag(incr), lv_creal(incr)); + + const unsigned int halfPoints = num_points / 2; + + + for(i = 0; i < (unsigned int)(halfPoints/ROTATOR_RELOAD); i++) { + for(j = 0; j < ROTATOR_RELOAD; ++j) { + + aVal = _mm_load_ps((float*)aPtr); + + yl = _mm_moveldup_ps(phase_Val); + yh = _mm_movehdup_ps(phase_Val); + ylp = _mm_moveldup_ps(inc_Val); + yhp = _mm_movehdup_ps(inc_Val); + + tmp1 = _mm_mul_ps(aVal, yl); + tmp1p = _mm_mul_ps(phase_Val, ylp); + + aVal = _mm_shuffle_ps(aVal, aVal, 0xB1); + phase_Val = _mm_shuffle_ps(phase_Val, phase_Val, 0xB1); + tmp2 = _mm_mul_ps(aVal, yh); + tmp2p = _mm_mul_ps(phase_Val, yhp); + + z = _mm_addsub_ps(tmp1, tmp2); + phase_Val = _mm_addsub_ps(tmp1p, tmp2p); + + _mm_store_ps((float*)cPtr, z); + + aPtr += 2; + cPtr += 2; + } + tmp1 = _mm_mul_ps(phase_Val, phase_Val); + tmp2 = _mm_hadd_ps(tmp1, tmp1); + tmp1 = _mm_shuffle_ps(tmp2, tmp2, 0xD8); + phase_Val = _mm_div_ps(phase_Val, tmp1); + } + for(i = 0; i < halfPoints%ROTATOR_RELOAD; ++i) { + aVal = _mm_load_ps((float*)aPtr); + + yl = _mm_moveldup_ps(phase_Val); + yh = _mm_movehdup_ps(phase_Val); + ylp = _mm_moveldup_ps(inc_Val); + yhp = _mm_movehdup_ps(inc_Val); + + tmp1 = _mm_mul_ps(aVal, yl); + + tmp1p = _mm_mul_ps(phase_Val, ylp); + + aVal = _mm_shuffle_ps(aVal, aVal, 0xB1); + phase_Val = _mm_shuffle_ps(phase_Val, phase_Val, 0xB1); + tmp2 = _mm_mul_ps(aVal, yh); + tmp2p = _mm_mul_ps(phase_Val, yhp); + + z = _mm_addsub_ps(tmp1, tmp2); + phase_Val = _mm_addsub_ps(tmp1p, tmp2p); + + _mm_store_ps((float*)cPtr, z); + + aPtr += 2; + cPtr += 2; + } + + _mm_storeu_ps((float*)phase_Ptr, phase_Val); + for(i = 0; i < num_points%2; ++i) { + *cPtr++ = *aPtr++ * phase_Ptr[0]; + phase_Ptr[0] *= (phase_inc); + } + + (*phase) = phase_Ptr[0]; + +} + +#endif /* LV_HAVE_SSE4_1 */ + + +#ifdef LV_HAVE_AVX +#include <immintrin.h> + +/*! + \brief rotate input vector at fixed rate per sample from initial phase offset + \param outVector The vector where the results will be stored + \param inVector Vector to be rotated + \param phase_inc rotational velocity + \param phase initial phase offset + \param num_points The number of values in inVector to be rotated and stored into cVector +*/ + + + + +static inline void volk_32fc_s32fc_x2_rotator_32fc_a_avx(lv_32fc_t* outVector, const lv_32fc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points){ + *phase = lv_cmake(1.0, 0.0); + lv_32fc_t* cPtr = outVector; + const lv_32fc_t* aPtr = inVector; + lv_32fc_t incr = 1; + lv_32fc_t phase_Ptr[4] = {(*phase), (*phase), (*phase), (*phase)}; + + unsigned int i, j = 0; + + for(i = 0; i < 4; ++i) { + phase_Ptr[i] *= incr; + incr *= (phase_inc); + } + + /*printf("%f, %f\n", lv_creal(phase_Ptr[0]), lv_cimag(phase_Ptr[0])); + printf("%f, %f\n", lv_creal(phase_Ptr[1]), lv_cimag(phase_Ptr[1])); + 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; + + 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; + + + for(i = 0; i < (unsigned int)(fourthPoints/ROTATOR_RELOAD); i++) { + for(j = 0; j < ROTATOR_RELOAD; ++j) { + + aVal = _mm256_load_ps((float*)aPtr); + + yl = _mm256_moveldup_ps(phase_Val); + yh = _mm256_movehdup_ps(phase_Val); + ylp = _mm256_moveldup_ps(inc_Val); + yhp = _mm256_movehdup_ps(inc_Val); + + tmp1 = _mm256_mul_ps(aVal, yl); + tmp1p = _mm256_mul_ps(phase_Val, ylp); + + aVal = _mm256_shuffle_ps(aVal, aVal, 0xB1); + phase_Val = _mm256_shuffle_ps(phase_Val, phase_Val, 0xB1); + tmp2 = _mm256_mul_ps(aVal, yh); + tmp2p = _mm256_mul_ps(phase_Val, yhp); + + z = _mm256_addsub_ps(tmp1, tmp2); + phase_Val = _mm256_addsub_ps(tmp1p, tmp2p); + + _mm256_store_ps((float*)cPtr, z); + + aPtr += 4; + cPtr += 4; + } + tmp1 = _mm256_mul_ps(phase_Val, phase_Val); + tmp2 = _mm256_hadd_ps(tmp1, tmp1); + tmp1 = _mm256_shuffle_ps(tmp2, tmp2, 0xD8); + phase_Val = _mm256_div_ps(phase_Val, tmp1); + } + for(i = 0; i < fourthPoints%ROTATOR_RELOAD; ++i) { + aVal = _mm256_load_ps((float*)aPtr); + + yl = _mm256_moveldup_ps(phase_Val); + yh = _mm256_movehdup_ps(phase_Val); + ylp = _mm256_moveldup_ps(inc_Val); + yhp = _mm256_movehdup_ps(inc_Val); + + tmp1 = _mm256_mul_ps(aVal, yl); + + tmp1p = _mm256_mul_ps(phase_Val, ylp); + + aVal = _mm256_shuffle_ps(aVal, aVal, 0xB1); + phase_Val = _mm256_shuffle_ps(phase_Val, phase_Val, 0xB1); + tmp2 = _mm256_mul_ps(aVal, yh); + tmp2p = _mm256_mul_ps(phase_Val, yhp); + + z = _mm256_addsub_ps(tmp1, tmp2); + phase_Val = _mm256_addsub_ps(tmp1p, tmp2p); + + _mm256_store_ps((float*)cPtr, z); + + aPtr += 4; + cPtr += 4; + } + + _mm256_storeu_ps((float*)phase_Ptr, phase_Val); + for(i = 0; i < num_points%4; ++i) { + *cPtr++ = *aPtr++ * phase_Ptr[0]; + phase_Ptr[0] *= (phase_inc); + } + + (*phase) = phase_Ptr[0]; + +} + +#endif /* LV_HAVE_AVX */ + + + + + + + + +#endif /* INCLUDED_volk_32fc_s32fc_rotator_32fc_a_H */ diff --git a/volk/lib/CMakeLists.txt b/volk/lib/CMakeLists.txt index b491f94bb..8288786c9 100644 --- a/volk/lib/CMakeLists.txt +++ b/volk/lib/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011-2012 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 @@ -16,6 +16,31 @@ # ######################################################################## +# header file detection +######################################################################## +include(CheckIncludeFile) +CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H) +if(HAVE_CPUID_H) + add_definitions(-DHAVE_CPUID_H) +endif() + +CHECK_INCLUDE_FILE(intrin.h HAVE_INTRIN_H) +if(HAVE_INTRIN_H) + add_definitions(-DHAVE_INTRIN_H) +endif() + +CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H) +if(HAVE_FENV_H) + add_definitions(-DHAVE_FENV_H) +endif() + +CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H) +if(HAVE_DLFCN_H) + add_definitions(-DHAVE_DLFCN_H) + list(APPEND volk_libraries ${CMAKE_DL_LIBS}) +endif() + +######################################################################## # Setup the compiler name ######################################################################## set(COMPILER_NAME ${CMAKE_C_COMPILER_ID}) @@ -23,235 +48,183 @@ if(MSVC) #its not set otherwise set(COMPILER_NAME MSVC) endif() +message(STATUS "Compiler name: ${COMPILER_NAME}") + if(NOT DEFINED COMPILER_NAME) message(FATAL_ERROR "COMPILER_NAME undefined. Volk build may not support this compiler.") endif() ######################################################################## -# Parse the arches xml file: -# Test each arch to see if the compiler supports the flag. -# If the test passes append the arch to the available list. +# detect x86 flavor of CPU ######################################################################## -#extract the compiler lines from the xml file using abusive python - - - -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda b: ','.join([','.join([b.attributes['name'].value,item.attributes['name'].value,item.firstChild.data]) for item in b.getElementsByTagName('remap')]), minidom.parse('${CMAKE_SOURCE_DIR}/gen/compilers.xml').getElementsByTagName('compiler')))" - - OUTPUT_VARIABLE compiler_lines OUTPUT_STRIP_TRAILING_WHITESPACE -) - -foreach(thing ${compiler_lines}) - string(REGEX REPLACE "," ";" thing_list ${thing}) - list(FIND thing_list ${COMPILER_NAME} check_val) - if(NOT ("${check_val}" STREQUAL "-1")) - string(REGEX REPLACE "${COMPILER_NAME}," ";" filter_string ${thing}) - endif() -endforeach() - +if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^(i.86|x86|x86_64|amd64)$") + message(STATUS "x86* CPU detected") + set(CPU_IS_x86 TRUE) +endif() -#extract compiler prefixes from the xml file using abusive python +######################################################################## +# determine passing architectures based on compile flag tests +######################################################################## execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda b: ','.join([','.join([b.attributes['name'].value,item.firstChild.data]) for item in b.getElementsByTagName('prefix')]), minidom.parse('${CMAKE_SOURCE_DIR}/gen/compilers.xml').getElementsByTagName('compiler')))" - - OUTPUT_VARIABLE compiler_prefixes OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_compile_utils.py + --mode "arch_flags" --compiler "${COMPILER_NAME}" + OUTPUT_VARIABLE arch_flag_lines OUTPUT_STRIP_TRAILING_WHITESPACE ) -foreach(thing ${compiler_prefixes}) - string(REGEX REPLACE "," ";" thing_list ${thing}) - list(FIND thing_list ${COMPILER_NAME} check_val) - if(NOT ("${check_val}" STREQUAL "-1")) - list(GET thing_list "1" prefix) +macro(check_arch arch_name) + set(flags ${ARGN}) + set(have_${arch_name} TRUE) + foreach(flag ${flags}) + include(CheckCXXCompilerFlag) + set(have_flag have${flag}) + execute_process( #make the have_flag have nice alphanum chars (just for looks/not necessary) + COMMAND ${PYTHON_EXECUTABLE} -c "import re; print(re.sub('\\W', '_', '${have_flag}'))" + OUTPUT_VARIABLE have_flag OUTPUT_STRIP_TRAILING_WHITESPACE + ) + CHECK_CXX_COMPILER_FLAG(${flag} ${have_flag}) + if (NOT ${have_flag}) + set(have_${arch_name} FALSE) + endif() + endforeach(flag) + if (have_${arch_name}) + list(APPEND available_archs ${arch_name}) endif() -endforeach() - - - - -#extract the arch lines from the xml file using abusive python -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s %s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data,a.getElementsByTagName('overrule')[0].firstChild.data,a.getElementsByTagName('overrule_val')[0].firstChild.data) if (len(a.getElementsByTagName('overrule'))) else '%s %s %s %s'%(a.attributes['name'].value,a.getElementsByTagName('flag')[0].firstChild.data,'no_overrule', 'no_overrule_val'), minidom.parse('${CMAKE_SOURCE_DIR}/gen/archs.xml').getElementsByTagName('arch')))" - - OUTPUT_VARIABLE arch_lines OUTPUT_STRIP_TRAILING_WHITESPACE -) +endmacro(check_arch) +foreach(line ${arch_flag_lines}) + string(REGEX REPLACE "," ";" arch_flags ${line}) + check_arch(${arch_flags}) +endforeach(line) +macro(OVERRULE_ARCH arch reason) + message(STATUS "${reason}, Overruled arch ${arch}") + list(REMOVE_ITEM available_archs ${arch}) +endmacro(OVERRULE_ARCH) - -#set the various overrule values (see archs.xml) -#a lot of this is translating between automake and cmake -if(NOT "${CROSSCOMPILE_MULTILIB}" STREQUAL "true") - set(MD_SUBCPU ${CMAKE_SYSTEM_PROCESSOR}) - #detect 32 or 64 bit compiler - if(MD_SUBCPU MATCHES "^(i.86|x86|x86_64|amd64)$") - include(CheckTypeSize) - check_type_size("void*" SIZEOF_VOID_P BUILTIN_TYPES_ONLY) - if (${SIZEOF_VOID_P} EQUAL 8) - set(MD_SUBCPU x86_64) - else() - set(MD_SUBCPU x86) - endif() +######################################################################## +# eliminate AVX on GCC < 4.4 +# even though it accepts -mavx, as won't assemble xgetbv, which we need +######################################################################## +if(CPU_IS_x86 AND COMPILER_NAME MATCHES "GNU") + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + if(GCC_VERSION VERSION_LESS "4.4") + OVERRULE_ARCH(avx "GCC missing xgetbv") endif() endif() -if(NOT "${ORC_FOUND}" STREQUAL "TRUE") - set(LV_HAVE_ORC "no") -endif() - +######################################################################## +# implement overruling in the ORC case, +# since ORC always passes flag detection +######################################################################## +if(NOT ORC_FOUND) + OVERRULE_ARCH(orc "ORC support not found") +endif() - - - -macro(compiler_filter name flag) - set(filtered_flag ${flag}) - foreach(thing ${filter_string}) - string(REGEX REPLACE "," ";" flagmap ${thing}) - list(GET flagmap "0" key) - list(GET flagmap "1" val) - string(REGEX MATCH "^${key}$" found ${flag}) - if("${found}" STREQUAL "${key}") - string(REGEX REPLACE "^${key}$" "${val}" filtered_flag ${flag}) - endif() - endforeach() - set(${name}_flag "${prefix}${filtered_flag}") -endmacro() - - - - - - - -macro(handle_arch name flag overrule overrule_val) - - #handle overrule - if("${${overrule}}" STREQUAL "${overrule_val}") - set(have_${name} FALSE) - message(STATUS "${name} overruled") - #handle special case for none flag - elseif(${flag} STREQUAL "none") - set(have_${name} TRUE) - #otherwise test the flag(s) against the compiler - else() - include(CheckCXXCompilerFlag) - string(REGEX REPLACE "," ";" flag_list ${flag}) - set(have_${name} 1) - foreach(thing ${flag_list}) - compiler_filter(${name} ${thing}) - CHECK_CXX_COMPILER_FLAG(${${name}_flag} have_${thing}) - if(NOT (${have_${name}} AND ("${have_${thing}}" STREQUAL "1"))) - set(have_${name} 0) - endif() - endforeach() +######################################################################## +# implement overruling in the non-multilib case +# this makes things work when both -m32 and -m64 pass +######################################################################## +if(NOT CROSSCOMPILE_MULTILIB AND CPU_IS_x86) + include(CheckTypeSize) + check_type_size("void*[8]" SIZEOF_CPU BUILTIN_TYPES_ONLY) + if (${SIZEOF_CPU} EQUAL 64) + OVERRULE_ARCH(32 "CPU width is 64 bits") endif() - - if(have_${name}) - list(APPEND available_arches ${name}) + if (${SIZEOF_CPU} EQUAL 32) + OVERRULE_ARCH(64 "CPU width is 32 bits") endif() +endif() -endmacro(handle_arch) - -#create a list of available arches -foreach(arch_line ${arch_lines}) - string(REPLACE " " ";" args "${arch_line}") - handle_arch(${args}) -endforeach(arch_line) - -message(STATUS "Available arches: ${available_arches}") +######################################################################## +# done overrules! print the result +######################################################################## +message(STATUS "Available architectures: ${available_archs}") ######################################################################## -# Parse the machines xml file: -# Test each machine to see if its arch dependencies are supported. -# Build a list of supported machines and the machine definitions. +# determine available machines given the available architectures ######################################################################## -#extract the machine lines from the xml file using crazy python execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c - "from xml.dom import minidom; print ';'.join(map(lambda a: '%s %s'%(a.attributes['name'].value,a.getElementsByTagName('archs')[0].firstChild.data),minidom.parse('${CMAKE_SOURCE_DIR}/gen/machines.xml').getElementsByTagName('machine')))" - OUTPUT_VARIABLE machine_lines OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_compile_utils.py + --mode "machines" --archs "${available_archs}" + OUTPUT_VARIABLE available_machines OUTPUT_STRIP_TRAILING_WHITESPACE ) -macro(handle_machine1 name) - unset(machine_flags) - string(TOUPPER LV_MACHINE_${name} machine_def) - - #check if all the arches are supported - foreach(arch ${ARGN}) - set(is_match ${have_${arch}}) - if(NOT is_match) - set(is_match FALSE) - break() - endif(NOT is_match) - set(machine_flags "${machine_flags} ${${arch}_flag}") - endforeach(arch) - - string(REGEX REPLACE "^[ \t]+" "" machine_flags "${machine_flags}") - - if(is_match) - #this is a match, append the source and set its flags - set(machine_source ${CMAKE_CURRENT_BINARY_DIR}/volk_machine_${name}.c) - set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS "${machine_flags}") - list(APPEND machine_sources ${machine_source}) - list(APPEND machine_defs ${machine_def}) - list(APPEND available_machines ${name}) - endif() -endmacro(handle_machine1) - -macro(handle_machine name) - set(arches ${ARGN}) - list(FIND arches "32|64" index) - if(${index} EQUAL -1) - handle_machine1(${name} ${arches}) - else() - list(REMOVE_ITEM arches "32|64") - handle_machine1(${name}_32 32 ${arches}) - handle_machine1(${name}_64 64 ${arches}) - endif() -endmacro(handle_machine) - -#setup the available machines -foreach(machine_line ${machine_lines}) - string(REPLACE " " ";" args "${machine_line}") - handle_machine(${args}) -endforeach(machine_line) +######################################################################## +# Implement machine overruling for redundant machines: +# A machine is redundant when expansion rules occur, +# and the arch superset passes configuration checks. +# When this occurs, eliminate the redundant machines +# to avoid unnecessary compilation of subset machines. +######################################################################## +foreach(arch orc 64 32) + foreach(machine_name ${available_machines}) + string(REPLACE "_${arch}" "" machine_name_no_arch ${machine_name}) + if (${machine_name} STREQUAL ${machine_name_no_arch}) + else() + list(REMOVE_ITEM available_machines ${machine_name_no_arch}) + endif() + endforeach(machine_name) +endforeach(arch) +######################################################################## +# done overrules! print the result +######################################################################## message(STATUS "Available machines: ${available_machines}") ######################################################################## # Create rules to run the volk generator ######################################################################## -#list of the generated sources -set(volk_gen_sources - ${CMAKE_BINARY_DIR}/include/volk/volk.h - ${CMAKE_BINARY_DIR}/lib/volk.c - ${CMAKE_BINARY_DIR}/lib/volk_init.h - ${CMAKE_BINARY_DIR}/include/volk/volk_typedefs.h - ${CMAKE_BINARY_DIR}/include/volk/volk_cpu.h - ${CMAKE_BINARY_DIR}/lib/volk_cpu.c - ${CMAKE_BINARY_DIR}/include/volk/volk_config_fixed.h - ${CMAKE_BINARY_DIR}/lib/volk_environment_init.c - ${CMAKE_BINARY_DIR}/lib/volk_environment_init.h - ${CMAKE_BINARY_DIR}/lib/volk_machines.h - ${CMAKE_BINARY_DIR}/lib/volk_machines.c - ${machine_sources} -) #dependencies are all python, xml, and header implementation files file(GLOB xml_files ${CMAKE_SOURCE_DIR}/gen/*.xml) file(GLOB py_files ${CMAKE_SOURCE_DIR}/gen/*.py) file(GLOB h_files ${CMAKE_SOURCE_DIR}/include/volk/*.h) -add_custom_command( - OUTPUT ${volk_gen_sources} - DEPENDS ${xml_files} ${py_files} ${h_files} - COMMAND ${PYTHON_EXECUTABLE} -B - ${CMAKE_SOURCE_DIR}/gen/volk_register.py - ${CMAKE_BINARY_DIR} -) +macro(gen_template tmpl output) + list(APPEND volk_gen_sources ${output}) + add_custom_command( + OUTPUT ${output} + DEPENDS ${xml_files} ${py_files} ${h_files} ${tmpl} + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_tmpl_utils.py + --input ${tmpl} --output ${output} ${ARGN} + ) +endmacro(gen_template) + +make_directory(${CMAKE_BINARY_DIR}/include/volk) + +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk.c) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_typedefs.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk_typedefs.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_cpu.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk_cpu.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_cpu.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk_cpu.c) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_config_fixed.tmpl.h ${CMAKE_BINARY_DIR}/include/volk/volk_config_fixed.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machines.tmpl.h ${CMAKE_BINARY_DIR}/lib/volk_machines.h) +gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machines.tmpl.c ${CMAKE_BINARY_DIR}/lib/volk_machines.c) + +foreach(machine_name ${available_machines}) + #generate machine source + set(machine_source ${CMAKE_CURRENT_BINARY_DIR}/volk_machine_${machine_name}.c) + gen_template(${CMAKE_SOURCE_DIR}/tmpl/volk_machine_xxx.tmpl.c ${machine_source} ${machine_name}) + + #determine machine flags + execute_process( + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_SOURCE_DIR}/gen/volk_compile_utils.py + --mode "machine_flags" --machine "${machine_name}" --compiler "${COMPILER_NAME}" + OUTPUT_VARIABLE ${machine_name}_flags OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(${machine_name}_flags) + set_source_files_properties(${machine_source} PROPERTIES COMPILE_FLAGS "${${machine_name}_flags}") + endif() + + #add to available machine defs + string(TOUPPER LV_MACHINE_${machine_name} machine_def) + list(APPEND machine_defs ${machine_def}) +endforeach(machine_name) ######################################################################## # Set local include directories first @@ -270,7 +243,7 @@ if(ORC_FOUND) #setup orc library usage include_directories(${ORC_INCLUDE_DIRS}) link_directories(${ORC_LIBRARY_DIRS}) - add_definitions(-DLV_HAVE_ORC) + list(APPEND volk_libraries ${ORC_LIBRARIES}) #setup orc functions file(GLOB orc_files ${CMAKE_SOURCE_DIR}/orc/*.orc) @@ -313,16 +286,15 @@ PROPERTIES COMPILE_DEFINITIONS "${machine_defs}") if(MSVC) #add compatibility includes for stdint types - include_directories(${CMAKE_SOURCE_DIR}/msvc) + include_directories(${CMAKE_SOURCE_DIR}/cmake/msvc) + add_definitions(-DHAVE_CONFIG_H) #compile the sources as C++ due to the lack of complex.h under MSVC set_source_files_properties(${volk_sources} PROPERTIES LANGUAGE CXX) endif() #create the volk runtime library add_library(volk SHARED ${volk_sources}) -if(ORC_FOUND) - target_link_libraries(volk ${ORC_LIBRARIES}) -endif(ORC_FOUND) +target_link_libraries(volk ${volk_libraries}) set_target_properties(volk PROPERTIES SOVERSION ${LIBVER}) set_target_properties(volk PROPERTIES DEFINE_SYMBOL "volk_EXPORTS") diff --git a/volk/lib/gcc_x86_cpuid.h b/volk/lib/gcc_x86_cpuid.h index e0254f192..3c3f47b00 100644 --- a/volk/lib/gcc_x86_cpuid.h +++ b/volk/lib/gcc_x86_cpuid.h @@ -5,16 +5,16 @@ * 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. - * + * * This file 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. - * + * * Under Section 7 of GPL version 3, you are granted additional * permissions described in the GCC Runtime Library Exception, version * 3.1, as published by the Free Software Foundation. - * + * * You should have received a copy of the GNU General Public License and * a copy of the GCC Runtime Library Exception along with this program; * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see diff --git a/volk/lib/qa_utils.cc b/volk/lib/qa_utils.cc index c15979b3f..4e361aece 100644 --- a/volk/lib/qa_utils.cc +++ b/volk/lib/qa_utils.cc @@ -15,6 +15,7 @@ #include <volk/volk_common.h> #include <boost/typeof/typeof.hpp> #include <boost/type_traits.hpp> +#include <stdio.h> float uniform() { return 2.0 * ((float) rand() / RAND_MAX - 0.5); // uniformly (-1, 1) @@ -168,6 +169,7 @@ static void get_signatures_from_name(std::vector<volk_type_t> &inputsig, } //we don't need an output signature (some fn's operate on the input data, "in place"), but we do need at least one input! assert(inputsig.size() != 0); + } inline void run_cast_test1(volk_fn_1arg func, std::vector<void *> &buffs, unsigned int vlen, unsigned int iter, std::string arch) { @@ -261,7 +263,8 @@ bool run_volk_tests(struct volk_func_desc desc, lv_32fc_t scalar, int vlen, int iter, - std::vector<std::string> *best_arch_vector = 0 + std::vector<std::string> *best_arch_vector = 0, + std::string puppet_master_name = "NULL" ) { std::cout << "RUN_VOLK_TESTS: " << name << std::endl; @@ -279,16 +282,16 @@ bool run_volk_tests(struct volk_func_desc desc, //now we have to get a function signature by parsing the name std::vector<volk_type_t> inputsig, outputsig; get_signatures_from_name(inputsig, outputsig, name); - + //pull the input scalars into their own vector std::vector<volk_type_t> inputsc; for(size_t i=0; i<inputsig.size(); i++) { if(inputsig[i].is_scalar) { inputsc.push_back(inputsig[i]); inputsig.erase(inputsig.begin() + i); + i -= 1; } } - //for(int i=0; i<inputsig.size(); i++) std::cout << "Input: " << inputsig[i].str << std::endl; //for(int i=0; i<outputsig.size(); i++) std::cout << "Output: " << outputsig[i].str << std::endl; std::vector<void *> inbuffs; @@ -450,7 +453,12 @@ bool run_volk_tests(struct volk_func_desc desc, std::cout << "Best arch: " << best_arch << std::endl; if(best_arch_vector) { - best_arch_vector->push_back(name + std::string(" ") + best_arch); + if(puppet_master_name == "NULL") { + best_arch_vector->push_back(name + std::string(" ") + best_arch); + } + else { + best_arch_vector->push_back(puppet_master_name + std::string(" ") + best_arch); + } } return fail_global; diff --git a/volk/lib/qa_utils.h b/volk/lib/qa_utils.h index b998df852..1e639ac3c 100644 --- a/volk/lib/qa_utils.h +++ b/volk/lib/qa_utils.h @@ -21,10 +21,12 @@ volk_type_t volk_type_from_string(std::string); float uniform(void); void random_floats(float *buf, unsigned n); -bool run_volk_tests(struct volk_func_desc, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *); +bool run_volk_tests(struct volk_func_desc, void(*)(), std::string, float, lv_32fc_t, int, int, std::vector<std::string> *, std::string); -#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) BOOST_AUTO_TEST_CASE(func##_test) { BOOST_CHECK_EQUAL(run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, 0), 0); } -#define VOLK_PROFILE(func, tol, scalar, len, iter, results) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results) + +#define VOLK_RUN_TESTS(func, tol, scalar, len, iter) BOOST_AUTO_TEST_CASE(func##_test) { BOOST_CHECK_EQUAL(run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, 0, "NULL"), 0); } +#define VOLK_PROFILE(func, tol, scalar, len, iter, results) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, "NULL") +#define VOLK_PUPPET_PROFILE(func, puppet_master_func, tol, scalar, len, iter, results) run_volk_tests(func##_get_func_desc(), (void (*)())func##_manual, std::string(#func), tol, scalar, len, iter, results, std::string(#puppet_master_func)) typedef void (*volk_fn_1arg)(void *, unsigned int, const char*); //one input, operate in place typedef void (*volk_fn_2arg)(void *, void *, unsigned int, const char*); typedef void (*volk_fn_3arg)(void *, void *, void *, unsigned int, const char*); diff --git a/volk/lib/testqa.cc b/volk/lib/testqa.cc index 593087f85..aac676729 100644 --- a/volk/lib/testqa.cc +++ b/volk/lib/testqa.cc @@ -55,7 +55,7 @@ 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_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, 32768, 20460, 1); +VOLK_RUN_TESTS(volk_32f_x2_s32f_interleave_16ic_a, 1, 32767, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_interleave_32fc_a, 0, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_max_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_x2_min_32f_a, 1e-4, 0, 20460, 1); @@ -101,3 +101,4 @@ VOLK_RUN_TESTS(volk_32fc_s32fc_multiply_32fc_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32fc_s32fc_multiply_32fc_u, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_s32f_multiply_32f_a, 1e-4, 0, 20460, 1); VOLK_RUN_TESTS(volk_32f_s32f_multiply_32f_u, 1e-4, 0, 20460, 1); +VOLK_RUN_TESTS(volk_32fc_s32fc_rotatorpuppet_32fc_a, 1e-2, (lv_32fc_t)lv_cmake(0.953939201, 0.3), 20460, 1); diff --git a/volk/libvector_replace.sh b/volk/libvector_replace.sh deleted file mode 100755 index e1940c00f..000000000 --- a/volk/libvector_replace.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -cd $1 -files=`ls` -for file in $files -do - sed 's/libvector/volk/g' < $file > tempfile - sed 's/LIBVECTOR/VOLK/g' < tempfile > $file -done -for file in $files -do - echo $file > tempfile - newfile=`sed 's/libvector/volk/g' < tempfile` - if (test "$file" != "$newfile"); then - mv $file $newfile - echo "changed $file to $newfile" - fi -done diff --git a/volk/python/__init__.py b/volk/python/__init__.py deleted file mode 100644 index 7c9c4a0c6..000000000 --- a/volk/python/__init__.py +++ /dev/null @@ -1,53 +0,0 @@ -# -# 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 this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# - -# The presence of this file turns this directory into a Python package - -# ---------------------------------------------------------------- -# Temporary workaround for ticket:181 (swig+python problem) -import sys -_RTLD_GLOBAL = 0 -try: - from dl import RTLD_GLOBAL as _RTLD_GLOBAL -except ImportError: - try: - from DLFCN import RTLD_GLOBAL as _RTLD_GLOBAL - except ImportError: - pass - -if _RTLD_GLOBAL != 0: - _dlopenflags = sys.getdlopenflags() - sys.setdlopenflags(_dlopenflags|_RTLD_GLOBAL) -# ---------------------------------------------------------------- - - -# import swig generated symbols into the volk namespace -from volk_swig import * - -# import any pure python here -# from volk_foo import bar -# from volk_baz import * - - -# ---------------------------------------------------------------- -# Tail of workaround -if _RTLD_GLOBAL != 0: - sys.setdlopenflags(_dlopenflags) # Restore original flags -# ---------------------------------------------------------------- diff --git a/volk/python/volk.i b/volk/python/volk.i deleted file mode 100644 index d678a9120..000000000 --- a/volk/python/volk.i +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -%feature("autodoc", "1"); // generate python docstrings - -%include "exception.i" -%import "gnuradio.i" // the common stuff - -%{ -#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix -#include <stdexcept> -%} - -// ---------------------------------------------------------------- - -/* - * Gather all .i files in this directory together. - */ - -%{ - -// The .h files -#include <volk/volk_square_ff.h> - -%} - -// The .i files -%include <volk_square_ff.i> - diff --git a/volk/tmpl/volk.tmpl.c b/volk/tmpl/volk.tmpl.c new file mode 100644 index 000000000..c3a1544ff --- /dev/null +++ b/volk/tmpl/volk.tmpl.c @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#include <volk/volk_common.h> +#include "volk_machines.h" +#include <volk/volk_typedefs.h> +#include <volk/volk_cpu.h> +#include "volk_rank_archs.h" +#include <volk/volk.h> +#include <stdio.h> +#include <string.h> + +struct volk_machine *get_machine(void) { + extern struct volk_machine *volk_machines[]; + extern unsigned int n_volk_machines; + static struct volk_machine *machine = NULL; + + if(machine != NULL) return machine; + else { + unsigned int max_score = 0; + unsigned int i; + for(i=0; i<n_volk_machines; i++) { + if(!(volk_machines[i]->caps & (~volk_get_lvarch()))) { + if(volk_machines[i]->caps > max_score) { + max_score = volk_machines[i]->caps; + machine = volk_machines[i]; + } + } + } + printf("Using Volk machine: %s\n", machine->name); + return machine; + } +} + +unsigned int volk_get_alignment(void) { + return get_machine()->alignment; +} + +#for $kern in $kernels + +void get_$(kern.name)($kern.arglist_namedefs) { + $kern.name = get_machine()->$(kern.name)_archs[volk_rank_archs( + get_machine()->$(kern.name)_indices, + get_machine()->$(kern.name)_arch_defs, + get_machine()->$(kern.name)_n_archs, + get_machine()->$(kern.name)_name, + volk_get_lvarch() + )]; + $(kern.name)($kern.arglist_names); +} + +$kern.pname $kern.name = &get_$(kern.name); + +void $(kern.name)_manual($kern.arglist_namedefs, const char* arch) { + const size_t index = get_index( + get_machine()->$(kern.name)_indices, + get_machine()->$(kern.name)_n_archs, + arch + ); + get_machine()->$(kern.name)_archs[index]( + $kern.arglist_names + ); +} + +struct volk_func_desc $(kern.name)_get_func_desc(void) { + struct volk_func_desc desc = { + get_machine()->$(kern.name)_indices, + get_machine()->$(kern.name)_arch_defs, + get_machine()->$(kern.name)_n_archs + }; + return desc; +} + +#end for diff --git a/volk/tmpl/volk.tmpl.h b/volk/tmpl/volk.tmpl.h new file mode 100644 index 000000000..161579e46 --- /dev/null +++ b/volk/tmpl/volk.tmpl.h @@ -0,0 +1,48 @@ +/* + * 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_VOLK_RUNTIME +#define INCLUDED_VOLK_RUNTIME + +#include <volk/volk_typedefs.h> +#include <volk/volk_config_fixed.h> +#include <volk/volk_common.h> +#include <volk/volk_complex.h> + +__VOLK_DECL_BEGIN + +struct volk_func_desc { + const char **indices; + const int *arch_defs; + const int n_archs; +}; + +VOLK_API unsigned int volk_get_alignment(void); + +#for $kern in $kernels +extern VOLK_API $kern.pname $kern.name; +extern VOLK_API void $(kern.name)_manual($kern.arglist_namedefs, const char* arch); +extern VOLK_API struct volk_func_desc $(kern.name)_get_func_desc(void); +#end for + +__VOLK_DECL_END + +#endif /*INCLUDED_VOLK_RUNTIME*/ diff --git a/volk/tmpl/volk_config_fixed.tmpl.h b/volk/tmpl/volk_config_fixed.tmpl.h new file mode 100644 index 000000000..e1c01ae77 --- /dev/null +++ b/volk/tmpl/volk_config_fixed.tmpl.h @@ -0,0 +1,29 @@ +/* + * 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_VOLK_CONFIG_FIXED_H +#define INCLUDED_VOLK_CONFIG_FIXED_H + +#for $i, $arch in enumerate($archs) +#define LV_$(arch.name.upper()) $i +#end for + +#endif /*INCLUDED_VOLK_CONFIG_FIXED*/ diff --git a/volk/tmpl/volk_cpu.tmpl.c b/volk/tmpl/volk_cpu.tmpl.c new file mode 100644 index 000000000..81fc679cb --- /dev/null +++ b/volk/tmpl/volk_cpu.tmpl.c @@ -0,0 +1,184 @@ +/* + * 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. + */ + +#include <volk/volk_cpu.h> +#include <volk/volk_config_fixed.h> +#include <stdlib.h> + +struct VOLK_CPU volk_cpu; + +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) + #define VOLK_CPU_x86 +#endif + +#if defined(VOLK_CPU_x86) + +//implement get cpuid for gcc compilers using a system or local copy of cpuid.h +#if defined(__GNUC__) + #if defined(HAVE_CPUID_H) + #include <cpuid.h> + #else + #include "gcc_x86_cpuid.h" + #endif + #define cpuid_x86(op, r) __get_cpuid(op, (unsigned int *)r+0, (unsigned int *)r+1, (unsigned int *)r+2, (unsigned int *)r+3) + + /* Return Intel AVX extended CPU capabilities register. + * This function will bomb on non-AVX-capable machines, so + * check for AVX capability before executing. + */ + #if __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 4 + static inline unsigned long long _xgetbv(unsigned int index){ + unsigned int eax, edx; + __asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index)); + return ((unsigned long long)edx << 32) | eax; + } + #define __xgetbv() _xgetbv(0) + #else + #define __xgetbv() 0 + #endif + +//implement get cpuid for MSVC compilers using __cpuid intrinsic +#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) + #include <intrin.h> + #define cpuid_x86(op, r) __cpuid(((int*)r), op) + + #if defined(_XCR_XFEATURE_ENABLED_MASK) + #define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) + #else + #define __xgetbv() 0 + #endif + +#else + #error "A get cpuid for volk is not available on this compiler..." +#endif //defined(__GNUC__) + +#endif //defined(VOLK_CPU_x86) + +static inline unsigned int cpuid_x86_bit(unsigned int reg, unsigned int op, unsigned int bit) { +#if defined(VOLK_CPU_x86) + unsigned int regs[4]; + cpuid_x86(op, regs); + return regs[reg] >> bit & 0x01; +#else + return 0; +#endif +} + +static inline unsigned int check_extended_cpuid(unsigned int val) { +#if defined(VOLK_CPU_x86) + unsigned int regs[4]; + cpuid_x86(0x80000000, regs); + return regs[0] >= val; +#else + return 0; +#endif +} + +static inline unsigned int get_avx_enabled(void) { +#if defined(VOLK_CPU_x86) + return __xgetbv() & 0x6; +#else + return 0; +#endif +} + +//neon detection is linux specific +#if defined(__arm__) && defined(__linux__) + #include <asm/hwcap.h> + #include <linux/auxvec.h> + #include <stdio.h> + #define VOLK_CPU_ARM +#endif + +static int has_neon(void){ +#if defined(VOLK_CPU_ARM) + FILE *auxvec_f; + unsigned long auxvec[2]; + unsigned int found_neon = 0; + auxvec_f = fopen("/proc/self/auxv", "rb"); + if(!auxvec_f) return 0; + + //so auxv is basically 32b of ID and 32b of value + //so it goes like this + while(!found_neon && auxvec_f) { + fread(auxvec, sizeof(unsigned long), 2, auxvec_f); + if((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_NEON)) + found_neon = 1; + } + + fclose(auxvec_f); + return found_neon; +#else + return 0; +#endif +} + +static int has_ppc(void){ +#ifdef __PPC__ + return 1; +#else + return 0; +#endif +} + +#for $arch in $archs +static int i_can_has_$arch.name (void) { + #for $check, $params in $arch.checks + if ($(check)($(', '.join($params))) == 0) return 0; + #end for + return 1; +} + +#end for + +#if defined(HAVE_FENV_H) + #include <fenv.h> + static inline void set_float_rounding(void){ + fesetround(FE_TONEAREST); + } +#elif defined(_MSC_VER) + #include <float.h> + static inline void set_float_rounding(void){ + unsigned int cwrd; + _controlfp_s(&cwrd, 0, 0); + _controlfp_s(&cwrd, _RC_NEAR, _MCW_RC); + } +#else + static inline void set_float_rounding(void){ + //do nothing + } +#endif + +void volk_cpu_init() { + #for $arch in $archs + volk_cpu.has_$arch.name = &i_can_has_$arch.name; + #end for + set_float_rounding(); +} + +unsigned int volk_get_lvarch() { + unsigned int retval = 0; + volk_cpu_init(); + #for $arch in $archs + retval += volk_cpu.has_$(arch.name)() << LV_$(arch.name.upper()); + #end for + return retval; +} diff --git a/volk/tmpl/volk_cpu.tmpl.h b/volk/tmpl/volk_cpu.tmpl.h new file mode 100644 index 000000000..4d66512e1 --- /dev/null +++ b/volk/tmpl/volk_cpu.tmpl.h @@ -0,0 +1,42 @@ +/* + * 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_VOLK_CPU_H +#define INCLUDED_VOLK_CPU_H + +#include <volk/volk_common.h> + +__VOLK_DECL_BEGIN + +struct VOLK_CPU { + #for $arch in $archs + int (*has_$arch.name) (); + #end for +}; + +extern struct VOLK_CPU volk_cpu; + +void volk_cpu_init (); +unsigned int volk_get_lvarch (); + +__VOLK_DECL_END + +#endif /*INCLUDED_VOLK_CPU_H*/ diff --git a/volk/tmpl/volk_machine_xxx.tmpl.c b/volk/tmpl/volk_machine_xxx.tmpl.c new file mode 100644 index 000000000..e405bd693 --- /dev/null +++ b/volk/tmpl/volk_machine_xxx.tmpl.c @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#set $this_machine = $machine_dict[$args[0]] +#set $arch_names = $this_machine.arch_names + +#for $arch in $this_machine.archs +#define LV_HAVE_$(arch.name.upper()) 1 +#end for + +#include <volk/volk_common.h> +#include "volk_machines.h" +#include <volk/volk_config_fixed.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#for $kern in $kernels +#include <volk/$(kern.name).h> +#end for + +######################################################################## +#def make_arch_have_list($archs) +$(' | '.join(['(1 << LV_%s)'%a.name.upper() for a in $archs]))#slurp +#end def + +######################################################################## +#def make_tag_str_list($tags) +{$(', '.join(['"%s"'%a for a in $tags]))}#slurp +#end def + +######################################################################## +#def make_tag_have_list($deps) +{$(', '.join([' | '.join(['(1 << LV_%s)'%a.upper() for a in d]) for d in $deps]))}#slurp +#end def + +######################################################################## +#def make_tag_kern_list($name, $tags) +{$(', '.join(['%s_%s'%($name, a) for a in $tags]))}#slurp +#end def + +struct volk_machine volk_machine_$(this_machine.name) = { + $make_arch_have_list($this_machine.archs), + "$this_machine.name", + $this_machine.alignment, + #for $kern in $kernels + #set $taglist, $tagdeps = $kern.get_tags($arch_names) + "$kern.name", + $make_tag_str_list($taglist), + $make_tag_have_list($tagdeps), + $make_tag_kern_list($kern.name, $taglist), + $(len($taglist)), + #end for +}; diff --git a/volk/tmpl/volk_machines.tmpl.c b/volk/tmpl/volk_machines.tmpl.c new file mode 100644 index 000000000..57dd03c98 --- /dev/null +++ b/volk/tmpl/volk_machines.tmpl.c @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#include <volk/volk_common.h> +#include <volk/volk_typedefs.h> +#include "volk_machines.h" + +struct volk_machine *volk_machines[] = { +#for $machine in $machines +#ifdef LV_MACHINE_$(machine.name.upper()) +&volk_machine_$(machine.name), +#endif +#end for +}; + +unsigned int n_volk_machines = sizeof(volk_machines)/sizeof(*volk_machines); diff --git a/volk/tmpl/volk_machines.tmpl.h b/volk/tmpl/volk_machines.tmpl.h new file mode 100644 index 000000000..b30e600ed --- /dev/null +++ b/volk/tmpl/volk_machines.tmpl.h @@ -0,0 +1,51 @@ +/* + * 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_LIBVOLK_MACHINES_H +#define INCLUDED_LIBVOLK_MACHINES_H + +#include <volk/volk_common.h> +#include <volk/volk_typedefs.h> + +__VOLK_DECL_BEGIN + +struct volk_machine { + const unsigned int caps; //capabilities (i.e., archs compiled into this machine, in the volk_get_lvarch format) + const char *name; + const unsigned int alignment; //the maximum byte alignment required for functions in this library + #for $kern in $kernels + const char *$(kern.name)_name; + const char *$(kern.name)_indices[$(len($archs))]; + const int $(kern.name)_arch_defs[$(len($archs))]; + const $(kern.pname) $(kern.name)_archs[$(len($archs))]; + const int $(kern.name)_n_archs; + #end for +}; + +#for $machine in $machines +#ifdef LV_MACHINE_$(machine.name.upper()) +extern struct volk_machine volk_machine_$(machine.name); +#endif +#end for + +__VOLK_DECL_END + +#endif //INCLUDED_LIBVOLK_MACHINES_H diff --git a/volk/tmpl/volk_typedefs.tmpl.h b/volk/tmpl/volk_typedefs.tmpl.h new file mode 100644 index 000000000..52a87242f --- /dev/null +++ b/volk/tmpl/volk_typedefs.tmpl.h @@ -0,0 +1,32 @@ +/* + * 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_VOLK_TYPEDEFS +#define INCLUDED_VOLK_TYPEDEFS + +#include <inttypes.h> +#include <volk/volk_complex.h> + +#for $kern in $kernels +typedef $kern.rettype (*$(kern.pname))($kern.arglist_defs); +#end for + +#endif /*INCLUDED_VOLK_TYPEDEFS*/ |